Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 23 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

## Description
Plugin Debug is a simple and modern library for collect some debug information of your plugin.
This library is inspired by Debug Paste of @IntellectualSites
This library is inspired by Debug Paste of @IntellectualSites [IntellectualSites](https://github.com/IntellectualSites)
As a backend we use from lucko [bytebin](https://github.com/lucko/bytebin) service to host/upload the debug files

## Motivation
We maintain now more than one plugin/software plugin in java. Now it's time to build an api/library to help us to provide better support for users there use our plugins.
Expand Down Expand Up @@ -37,30 +38,38 @@ dependencies {
```kt
dependencies {
// Core
implementation("dev.themeinerlp:plugin-debug:1.0.0")
implementation("dev.themeinerlp:plugin-debug:1.1.0")
// Bukkit Extension
implementation("dev.themeinerlp.plugin-debug:bukkit-extension:1.0.0")
implementation("dev.themeinerlp.plugin-debug:bukkit-extension:1.1.0")
}
```
</details>

Example code(Kotlin):
### Example

We have an example [gradle module](example) with an example bukkit command to retrieve a debug log.
Also, we provide already a pre-hosted web ui for view your logs.

The hosted ui follows this structure:
```
https://debugpaste.onelitefeather.net/#/BYTEBIN_CODE/ENCODED_URL/
```
* BYTEBIN_CODE
* The returned code from ByteBin Server when the upload is successfully
* ENCODED_URL
* The ByteBin Server URL encoded in a friendly style

---
### Example code(Kotlin):
```kt
// Example json object
// Example json object from GSON LIB
val obj = JsonObject()
obj.addProperty("Test", "Test")

val result =
DebugBuilder.builder(BYTEBIN_BASE_URL)
// For this is the bukkit extension required
.enableLatestLogSpigot() // Adds the paper last log
.defaultPaperDebugInformation() // Adds as a parseable yaml format some system relevant information from bukkit
// Adds a file from path wrapped in a placeholder object
.addFile(DebugFile(attollo.dataFolder.toPath().resolve("config.yml"),FileType.YAML,"Config as file object"))
// Adds a file from path
.addFile(attollo.dataFolder.toPath().resolve("config.yml"),FileType.YAML,"Config as file")
// Add yaml formatted string to the debug
.addYAML(attollo.config.saveToString(), "Config")
.addFile(DebugFile(Path.of("config", "config.yml"), FileType.YAML, "Config as file object"))
// Add a simple text to the debug
.addText("Text test", "Text test")
// Add json formatted string to the debug
Expand All @@ -76,19 +85,5 @@ val encodedUrl = URLEncoder.encode(
val code = result.code
// Prettified url
val openUrl = "https://debugpaste.onelitefeather.net/#/$code/$encodedUrl/"
val component = MiniMessage.miniMessage().deserialize("<#05b9ff>[Attollo] <yellow><click:OPEN_URL:'$openUrl'>Click <u>here</u> to open the debug paste</click>")
```
**For better formatting we used mini message also the two lines `enableLatestLogSpigot()` and `defaultPaperDebugInformation()` requires the Bukkit Extension.**

Example for java
```java
var obj = new JsonObject();
obj.addProperty("Test", "Test");

var builder = DebugBuilder.builder(BYTEBIN_BASE_URL);
builder = enableLatestLogSpigot(builder);
builder = defaultPaperDebugInformation(builder);
builder.addFile(new DebugFile(Path.of(""), FileType.YAML, "Config as file object"))
.addFile(Path.of(""), FileType.YAML, "Config as file");
var result = builder.upload();
val component = MiniMessage.miniMessage().deserialize("<#05b9ff>[Example] <yellow><click:OPEN_URL:'$openUrl'>Click <u>here</u> to open the debug paste</click>")
```
57 changes: 5 additions & 52 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import org.ajoberstar.grgit.Grgit
import java.util.*

plugins {
kotlin("jvm") version "1.8.21"
java
id("org.ajoberstar.grgit") version "5.2.0"
`java-library`
`maven-publish`
signing
id("org.jetbrains.dokka") version "1.8.10"
}

if (!File("$rootDir/.git").exists()) {
Expand All @@ -22,7 +21,7 @@ if (!File("$rootDir/.git").exists()) {
}

group = "dev.themeinerlp"
var baseVersion by extra("1.0.0")
var baseVersion by extra("1.1.0")
var extension by extra("")
var snapshot by extra("-SNAPSHOT")

Expand All @@ -44,73 +43,27 @@ repositories {
dependencies {
implementation("net.lingala.zip4j:zip4j:2.11.5")
implementation("com.google.code.gson:gson:2.10.1")
// Test
testImplementation("net.lingala.zip4j:zip4j:2.11.5")
testImplementation("com.google.code.gson:gson:2.10.1")
testImplementation(kotlin("test"))
}

tasks {
test {
useJUnitPlatform()
}
dokkaHtml {
dokkaSourceSets {
named("main") {
moduleName.set("Plugin Debug")
includes.from("module.md")
description = "A simple library to upload plugin debugs"
version = "%s%s".format(Locale.ROOT, baseVersion, snapshot)
}
}
}
dokkaJavadoc {
dokkaSourceSets {
named("main") {
moduleName.set("Plugin Debug")
description = "A simple library to upload plugin debugs"
includes.from("module.md")
version = "%s%s".format(Locale.ROOT, baseVersion, snapshot)
}
}
}
}

kotlin {
jvmToolchain(17)
sourceSets.all {
languageSettings {
languageVersion = "2.0"
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

val sourceJar by tasks.register<Jar>("kotlinJar") {
from(sourceSets.main.get().allSource)
archiveClassifier.set("sources")
}
val dokkaJavadocJar by tasks.register<Jar>("dokkaHtmlJar") {
dependsOn(rootProject.tasks.dokkaHtml)
from(rootProject.tasks.dokkaHtml.flatMap { it.outputDirectory })
archiveClassifier.set("html-docs")
}

val dokkaHtmlJar by tasks.register<Jar>("dokkaJavadocJar") {
dependsOn(rootProject.tasks.dokkaJavadoc)
from(rootProject.tasks.dokkaJavadoc.flatMap { it.outputDirectory })
archiveClassifier.set("javadoc")
}

publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components.findByName("java"))
groupId = "dev.themeinerlp"
artifactId = "plugin-debug"
version = "%s%s".format(Locale.ROOT, baseVersion, snapshot)
artifact(dokkaJavadocJar)
artifact(dokkaHtmlJar)
artifact(sourceJar)
pom {
name.set("Plugin debug")
description.set("A simple library to upload plugin debugs")
Expand Down
55 changes: 6 additions & 49 deletions bukkit-extension/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ import org.ajoberstar.grgit.Grgit
import java.util.*

plugins {
kotlin("jvm") version "1.8.21"
java
`java-library`
`maven-publish`
signing
id("org.jetbrains.dokka") version "1.8.10"
}

group = "dev.themeinerlp"
var baseVersion by extra("1.0.0")
var baseVersion by extra("1.1.0")
var extension by extra("")
var snapshot by extra("-SNAPSHOT")

Expand All @@ -34,58 +33,19 @@ dependencies {
compileOnly(rootProject)
compileOnly("io.papermc.paper:paper-api:1.19.4-R0.1-SNAPSHOT")
implementation("io.papermc:paperlib:1.0.8")
testImplementation(platform("org.junit:junit-bom:5.9.3"))
testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks {
test {
useJUnitPlatform()
}

dokkaHtml {
dokkaSourceSets {
named("main") {
moduleName.set("Plugin Debug Bukkit Extension")
description = "Extends the main api with some nice features for bukkit"
version = "%s%s".format(Locale.ROOT, baseVersion, snapshot)
}
}
}
dokkaJavadoc {
dokkaSourceSets {
named("main") {
moduleName.set("Plugin Debug Bukkit Extension")
description = "Extends the main api with some nice features for bukkit"
version = "%s%s".format(Locale.ROOT, baseVersion, snapshot)
}
}
}
}

kotlin {
jvmToolchain(17)
sourceSets.all {
languageSettings {
languageVersion = "2.0"
}
}
}

val sourceJar by tasks.register<Jar>("kotlinJar") {
from(sourceSets.main.get().allSource)
archiveClassifier.set("sources")
}
val dokkaJavadocJar by tasks.register<Jar>("dokkaHtmlJar") {
dependsOn(rootProject.tasks.dokkaHtml)
from(rootProject.tasks.dokkaHtml.flatMap { it.outputDirectory })
archiveClassifier.set("html-docs")
}

val dokkaHtmlJar by tasks.register<Jar>("dokkaJavadocJar") {
dependsOn(rootProject.tasks.dokkaJavadoc)
from(rootProject.tasks.dokkaJavadoc.flatMap { it.outputDirectory })
archiveClassifier.set("javadoc")
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

publishing {
Expand All @@ -95,9 +55,6 @@ publishing {
groupId = "dev.themeinerlp.plugin-debug"
artifactId = "bukkit-extension"
version = "%s%s".format(Locale.ROOT, baseVersion, snapshot)
artifact(dokkaJavadocJar)
artifact(dokkaHtmlJar)
artifact(sourceJar)
pom {
name.set("Bukkit Extension")
description.set("The extension for bukkit/paper/spigot for plugin debug")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package dev.themeinerlp.plugindebug;

import io.papermc.lib.PaperLib;
import io.papermc.paper.datapack.Datapack;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.regex.Pattern;

/**
* Bukkit Debug builder
*/
public final class BukkitDebugBuilder extends DebugBuilder<BukkitDebugBuilder> {

private final Pattern privacyRegex = Pattern.compile("\\b(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\\.(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\\.(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\\.(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\\b");
private BukkitDebugBuilder(String uploadServer) {
super(uploadServer);
}

/**
* Collects the latest log file from bukkit
* @return the builder
* @throws IOException if the file empty/null
*/
public BukkitDebugBuilder collectLatestSpigotLog() throws IOException {
var latestLogFile = Path.of("logs", "latest.log");
if (Files.size(latestLogFile) >= maxZipFileSize) throw new IllegalStateException(
String.format("Latest log file is to big only %d bytes allowed", maxZipFileSize)
);
var tempLogFile = Files.createTempFile(tempFile, ".log");
var cleanedList = Files.readAllLines(latestLogFile).stream().map(s -> s.replaceAll(privacyRegex.pattern(), "*")).toList();
Files.write(tempLogFile, cleanedList);
addFile(tempLogFile, FileType.LOG, "Latest Log");
return this;
}

/**
* Collects default paper debug information
* @return the bukkit builder
* @throws IOException if the file empty/null
*/

public BukkitDebugBuilder defaultPaperDebugInformation() throws IOException {
var tempLogFile = Files.createTempFile(tempFile, ".yaml");
var plugins = Arrays.asList(Bukkit.getServer().getPluginManager().getPlugins());
plugins.sort(this::sortPluginByName);
var debugInformation = new YamlConfiguration();
debugInformation.set("server.version", Bukkit.getVersion());
debugInformation.set("server.plugins", plugins.size());
for (Plugin plugin : plugins) {
var name = plugin.getName();
debugInformation.set(String.format("server.plugin.%s.version", name), plugin.getDescription().getVersion());
debugInformation.set(String.format("server.plugin.%s.main", name), plugin.getDescription().getMain());
debugInformation.set(String.format("server.plugin.%s.authors", name), plugin.getDescription().getAuthors());
debugInformation.set(String.format("server.plugin.%s.load-before", name), plugin.getDescription().getLoadBefore());
debugInformation.set(String.format("server.plugin.%s.dependencies", name), plugin.getDescription().getDepend());
debugInformation.set(String.format("server.plugin.%s.soft-dependencies", name), plugin.getDescription().getSoftDepend());
debugInformation.set(String.format("server.plugin.%s.provides", name), plugin.getDescription().getProvides());
debugInformation.set(String.format("server.plugin.%s.enabled", name), plugin.isEnabled());
}
if (PaperLib.isPaper()) {
var dataPacks = Bukkit.getServer().getDatapackManager().getEnabledPacks();
debugInformation.set("server.datapacks.count", dataPacks.size());
debugInformation.set("server.datapacks.packs", dataPacks.stream().map(Datapack::getName).toList());
}
var runtime = Runtime.getRuntime();
var rb = ManagementFactory.getRuntimeMXBean();
debugInformation.set("uptime", rb.getUptime());
debugInformation.set("jvm-flags", rb.getInputArguments());
debugInformation.set("free-memory", runtime.freeMemory());
debugInformation.set("max-memory", runtime.maxMemory());
debugInformation.set("total-memory", runtime.totalMemory());
debugInformation.set("available-processors", runtime.availableProcessors());
debugInformation.set("java-name", rb.getVmName());
debugInformation.set("java-version", System.getProperty("java.version"));
debugInformation.set("java-vendor", System.getProperty("java.vendor"));
debugInformation.set("operating-system", System.getProperty("os.name"));
debugInformation.set("os-version", System.getProperty("os.version"));
debugInformation.set("os-arch", System.getProperty("os.arch"));
addYAML(debugInformation.saveToString(), "Default Paper Debug Information");
return this;
}

private int sortPluginByName(@NotNull Plugin A, @NotNull Plugin B) {
return A.getName().compareTo(B.getName());
}

/**
* Creates a bukkit builder instance with the given bytebin server
*
* @param uploadServer bytebin server base url
*/
public static BukkitDebugBuilder builder(String uploadServer) {
return new BukkitDebugBuilder(uploadServer);
}

}
Loading