diff --git a/CREDITS.MD b/CREDITS.MD index b4a3ce8..528ad15 100644 --- a/CREDITS.MD +++ b/CREDITS.MD @@ -13,6 +13,7 @@ Here dependencies are used by custom anvil - [modrinth-publish](https://github.com/cloudnode-pro/modrinth-publish) by Zefir - [discord-webhook](https://github.com/tsickert/discord-webhook) by tsickert - Thanks [bstats](https://bstats.org/) for keeping me motivated +- And [FastStats](https://faststats.dev/) alternative to bstats in beta test - [ModrinthUpdateChecker](https://github.com/Clickism/ModrinthUpdateChecker) by Clickism and thanks to the modrinth team ### Compatibility diff --git a/README.md b/README.md index e1d7ec6..fe552b8 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Please note that 1.16.5 to 1.17.1 are not officially supported. Run at your own ### For custom enchantment plugin developers For information about the API, please refer to [the Wiki](https://github.com/alexcrea/CustomAnvil/wiki) \ -(Please note that the wiki is currently incomplete)​ +(Please note that the wiki is currently incomplete) --- @@ -76,7 +76,14 @@ For information about the API, please refer to [the Wiki](https://github.com/ale see [Here](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs) --- -Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923) for metric. You can [disable it](https://bstats.org/getting-started) if you like. +### Metric And Telemetry +Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923) +and [faststats](https://faststats.dev/project/customanvil/minecraft-plugin) for metric and error reporting. + +You can select specific telemetry or disable all in config.yml. \ +You can also [disable bstat](https://bstats.org/getting-started) and [faststats](https://faststats.dev/info) in their /plugin folder if you like too. + +faststats is in beta testing please report me or them any error you encounter ### Credits and Thanks Credits and thanks can be seen [here](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/CREDITS.md) diff --git a/build.gradle.kts b/build.gradle.kts index 5eb4561..903c988 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,6 +36,12 @@ repositories { // ExcellentEnchants maven(url = "https://repo.nightexpressdev.com/releases") + + // for fast stats + maven { + name = "thenextlvlReleases" + url = uri("https://repo.thenextlvl.net/releases") + } } val reobfNMS = providers.gradleProperty("subprojects.reobfnms") @@ -45,6 +51,9 @@ dependencies { // Spigot api compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") + // fast stats + implementation("dev.faststats.metrics:bukkit:0.16.0") + // minimessage implementation("net.kyori:adventure-text-minimessage:4.25.0") @@ -132,7 +141,7 @@ allprojects { // Set target version tasks.withType().configureEach { sourceCompatibility = - "16" // We aim for java 16 for minecraft 1.16.5. even if it not really suported by custom anvil. + "16" // We aim for java 16 for minecraft 1.16.5. even if it not really supported by custom anvil. targetCompatibility = "16" options.encoding = "UTF-8" @@ -156,7 +165,8 @@ tasks { archiveFileName.set(name) // Shadow necessary dependency - relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.inventoryframework") + relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.cuanvil.inventoryframework") + relocate("dev.faststats", "xyz.alexcrea.cuanvil.faststats") filesMatching("plugin.yml") { expand( diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index 0b543cd..47070ba 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -3,6 +3,19 @@ # You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! # +# What service of metric should custom anvil use +# Custom anvil collect generic information like server minecraft version, type, etc... +# It can also collect error information if error is happening (currently faststats only) +# It can also be disabled +# Please refer to README for public metric link +# Possible options: auto, bstat, faststats, disabled (auto by default) +metric_type: auto + +# Allow to report errors made caused by this plugin (only for faststats) +# This allows me to fix potentials issue that I'm not aware of +# Accept true or false (true by default) +metric_collect_errors: true + # All anvil cost will be capped to limit_repair_value if enabled. # # In other words: diff --git a/defaultconfigs/1.21.11/config.yml b/defaultconfigs/1.21.11/config.yml index 9a8eb9c..0d9e089 100644 --- a/defaultconfigs/1.21.11/config.yml +++ b/defaultconfigs/1.21.11/config.yml @@ -3,6 +3,19 @@ # You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! # +# What service of metric should custom anvil use +# Custom anvil collect generic information like server minecraft version, type, etc... +# It can also collect error information if error is happening (currently faststats only) +# It can also be disabled +# Please refer to README for public metric link +# Possible options: auto, bstat, faststats, disabled (auto by default) +metric_type: auto + +# Allow to report errors made caused by this plugin (only for faststats) +# This allows me to fix potentials issue that I'm not aware of +# Accept true or false (true by default) +metric_collect_errors: true + # All anvil cost will be capped to limit_repair_value if enabled. # # In other words: diff --git a/defaultconfigs/1.21.9/config.yml b/defaultconfigs/1.21.9/config.yml index 809bab9..d3538b2 100644 --- a/defaultconfigs/1.21.9/config.yml +++ b/defaultconfigs/1.21.9/config.yml @@ -3,6 +3,19 @@ # You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! # +# What service of metric should custom anvil use +# Custom anvil collect generic information like server minecraft version, type, etc... +# It can also collect error information if error is happening (currently faststats only) +# It can also be disabled +# Please refer to README for public metric link +# Possible options: auto, bstat, faststats, disabled (auto by default) +metric_type: auto + +# Allow to report errors made caused by this plugin (only for faststats) +# This allows me to fix potentials issue that I'm not aware of +# Accept true or false (true by default) +metric_collect_errors: true + # All anvil cost will be capped to limit_repair_value if enabled. # # In other words: diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml index 88eff1a..c1677fb 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -3,6 +3,19 @@ # You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! # +# What service of metric should custom anvil use +# Custom anvil collect generic information like server minecraft version, type, etc... +# It can also collect error information if error is happening (currently faststats only) +# It can also be disabled +# Please refer to README for public metric link +# Possible options: auto, bstat, faststats, disabled (auto by default) +metric_type: auto + +# Allow to report errors made caused by this plugin (only for faststats) +# This allows me to fix potentials issue that I'm not aware of +# Accept true or false (true by default) +metric_collect_errors: true + # All anvil cost will be capped to limit_repair_value if enabled. # # In other words: diff --git a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java index 2037e23..f6a7e80 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java +++ b/src/main/java/xyz/alexcrea/cuanvil/config/ConfigHolder.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable; import xyz.alexcrea.cuanvil.group.EnchantConflictManager; import xyz.alexcrea.cuanvil.group.ItemGroupManager; import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager; +import xyz.alexcrea.cuanvil.util.MetricsUtil; import java.io.File; import java.io.IOException; @@ -145,6 +146,7 @@ public abstract class ConfigHolder { sufficientSuccess = true; } catch (IOException e) { CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not copy backup saving config " + base.getName(), e); + MetricsUtil.INSTANCE.trackError(e); } } // save last backup @@ -275,6 +277,7 @@ public abstract class ConfigHolder { this.deletedConfigFile.createNewFile(); } catch (IOException e) { CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not create " + this.deletedConfigFile.getPath(), e); + MetricsUtil.INSTANCE.trackError(e); } loadDeletedListFile(false); @@ -312,6 +315,7 @@ public abstract class ConfigHolder { this.deletedListConfig.save(this.deletedConfigFile); } catch (IOException e) { CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not save " + this.deletedConfigFile.getPath(), e); + MetricsUtil.INSTANCE.trackError(e); return false; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java index 4634a11..854ed55 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentRegistry.java @@ -10,6 +10,7 @@ import xyz.alexcrea.cuanvil.enchant.bulk.BukkitEnchantBulkOperation; import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation; import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation; import xyz.alexcrea.cuanvil.enchant.wrapped.CABukkitEnchantment; +import xyz.alexcrea.cuanvil.util.MetricsUtil; import java.util.*; import java.util.logging.Level; @@ -85,11 +86,13 @@ public class CAEnchantmentRegistry { return false; } + var error = new IllegalStateException("enchantment " + enchantment.getKey() + " was already registered"); CustomAnvil.instance.getLogger().log(Level.WARNING, "Duplicate distinct registered enchantment. This should NOT happen any time.\n" + "If you are a custom anvil developer: Maybe custom anvil detected your enchantment as a bukkit enchantment. " + "you should maybe remove enchantment with the same key before registering yours", - new IllegalStateException("enchantment " + enchantment.getKey() + " was already registered")); + error); + MetricsUtil.INSTANCE.trackError(error); return false; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java index 56bf848..5839663 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java @@ -11,6 +11,7 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.util.MetricsUtil; import java.util.Arrays; import java.util.function.Supplier; @@ -41,6 +42,7 @@ public class ConfirmActionGui extends AbstractAskGui { success = onConfirm.get(); } catch (Exception e) { CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not process confirmation supplier.", e); + MetricsUtil.INSTANCE.trackError(e); success = false; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java index 99bba84..97bdfcb 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java @@ -25,6 +25,7 @@ import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.util.CasedStringUtil; +import xyz.alexcrea.cuanvil.util.MetricsUtil; import java.util.*; import java.util.function.Supplier; @@ -264,6 +265,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl updateGuiValues(); } catch (Exception e) { CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict, e); + MetricsUtil.INSTANCE.trackError(e); } // Save file configuration to disk @@ -308,6 +310,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl updateGuiValues(); } catch (Exception e) { CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict, e); + MetricsUtil.INSTANCE.trackError(e); } // Save file configuration to disk diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index 902b76d..9b2b696 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -22,7 +22,7 @@ import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener import xyz.alexcrea.cuanvil.update.ModrinthUpdateChecker import xyz.alexcrea.cuanvil.update.PluginSetDefault import xyz.alexcrea.cuanvil.update.UpdateHandler -import xyz.alexcrea.cuanvil.util.Metrics +import xyz.alexcrea.cuanvil.util.MetricsUtil import java.io.File import java.io.FileReader import java.util.logging.Level @@ -34,7 +34,6 @@ open class CustomAnvil : JavaPlugin() { companion object { // pluginIDS - private const val bstatsPluginId = 20923 private const val modrinthPluginID = "S75Ueiq9" // Permission string required to use the plugin's features @@ -118,7 +117,8 @@ open class CustomAnvil : JavaPlugin() { try { legacyCheck() } catch (e: Exception) { - logger.log(Level.SEVERE, "error trying to check for legacy system" , e) + logger.log(Level.SEVERE, "error trying to check for legacy system", e) + MetricsUtil.trackError(e) if(trySafeStart()) return } @@ -126,7 +126,8 @@ open class CustomAnvil : JavaPlugin() { try { prepareCommand() } catch (e: Exception) { - logger.log(Level.SEVERE, "error trying to register commands" , e) + logger.log(Level.SEVERE, "error trying to register commands", e) + MetricsUtil.trackError(e) if(trySafeStart()) return } @@ -136,6 +137,7 @@ open class CustomAnvil : JavaPlugin() { throw RuntimeException("Error loading configuration file") } catch (e: Exception) { logger.log(Level.SEVERE, "error occurred loading default configuration", e) + MetricsUtil.trackError(e) if(tryDirtyStart()) return } @@ -144,6 +146,7 @@ open class CustomAnvil : JavaPlugin() { DependencyManager.loadDependency() } catch (e: Exception) { logger.log(Level.SEVERE, "error loading dependency compatibility", e) + MetricsUtil.trackError(e) if(tryDirtyStart()) return } @@ -152,24 +155,28 @@ open class CustomAnvil : JavaPlugin() { registerListeners() } catch (e: Exception) { logger.log(Level.SEVERE, "error registering listeners", e) + MetricsUtil.trackError(e) if(tryDirtyStart()) return } // Load metrics - try { - Metrics(this, bstatsPluginId) - } catch (_: Exception) {} + MetricsUtil.loadMetrics(this) // Load other thing later. // It is so other dependent plugins can implement there event listener before we fire them. DependencyManager.scheduler.scheduleGlobally(this) { loadEnchantmentSystemDirty() } } + override fun onDisable() { + MetricsUtil.shutdownMetrics() + } + private fun loadEnchantmentSystemDirty() { try { loadEnchantmentSystem() } catch (e: Exception) { - logger.log(Level.SEVERE, "error initializing enchantment ssytem", e) + logger.log(Level.SEVERE, "error initializing enchantment system", e) + MetricsUtil.trackError(e) tryDirtyStart() } } @@ -196,7 +203,10 @@ open class CustomAnvil : JavaPlugin() { ModrinthUpdateChecker(modrinthPluginID, loader, null) .setFeatured(featured) - .setOnError { logger.log(Level.WARNING, "error trying to fetch latest update", it) } + .setOnError { + logger.log(Level.WARNING, "error trying to fetch latest update", it) + MetricsUtil.trackError(it) + } .checkVersion { latestVer: String? -> CustomAnvil.latestVer = latestVer if(latestVer == null || version.contains(latestVer)) return@checkVersion diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index afb009f..8bd76d2 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -21,6 +21,9 @@ object ConfigOptions { // Path for config values // ---------------------- + const val METRIC_TYPE = "metric_type" + const val METRIC_COLLECT_ERROR = "metric_collect_errors" + const val CAP_ANVIL_COST = "limit_repair_cost" const val MAX_ANVIL_COST = "limit_repair_value" const val REMOVE_ANVIL_COST_LIMIT = "remove_repair_limit" diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCmd.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCmd.kt index 2a46fa8..f1fcb88 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCmd.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCmd.kt @@ -6,6 +6,7 @@ import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.command.TabCompleter +import xyz.alexcrea.cuanvil.util.MetricsUtil import java.util.ArrayList class CustomAnvilCmd(plugin: CustomAnvil) : CommandExecutor, TabCompleter { @@ -20,7 +21,6 @@ class CustomAnvilCmd(plugin: CustomAnvil) : CommandExecutor, TabCompleter { "gui", editConfigCommand, "reload", ReloadExecutor(), "diagnostic", DiagnosticExecutor(), - //"debug", DebugExecutor(), ) init { @@ -38,10 +38,14 @@ class CustomAnvilCmd(plugin: CustomAnvil) : CommandExecutor, TabCompleter { args: Array ): Boolean { // Find sub command to execute based on the provided command name - val subcmd: CASubCommand? = if(args.isEmpty()) { - editConfigCommand + val subcmd: CASubCommand? + val newargs: Array + if(args.isEmpty()) { + subcmd = editConfigCommand + newargs = args }else { - commands[args[0].lowercase()] + subcmd = commands[args[0].lowercase()] + newargs = args.copyOfRange(1, args.size) } if(subcmd == null) { @@ -49,8 +53,13 @@ class CustomAnvilCmd(plugin: CustomAnvil) : CommandExecutor, TabCompleter { return true } - val newargs = args.copyOfRange(1, args.size) - return subcmd.executeCommand(sender, cmd, cmdstr, newargs) + try { + return subcmd.executeCommand(sender, cmd, cmdstr, newargs) + } catch (e: Throwable) { + MetricsUtil.trackError(e) + sender.sendMessage("§cError running this command") + return false + } } override fun onTabComplete( diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugExecutor.kt deleted file mode 100644 index e7cbe9e..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugExecutor.kt +++ /dev/null @@ -1,25 +0,0 @@ -package xyz.alexcrea.cuanvil.command - -import io.delilaheve.CustomAnvil -import org.bukkit.command.Command -import org.bukkit.command.CommandSender -import java.util.logging.Level - -class DebugExecutor : CASubCommand() { - - override fun executeCommand( - sender: CommandSender, - cmd: Command, - cmdstr: String, - args: Array - ): Boolean { - CustomAnvil.instance.logger.log(Level.SEVERE, "aaaaaaaaaaaaaaaaaaa"); - return true - } - - override fun tabCompleter(sender: CommandSender, args: Array, list: MutableList) { - //TODO - - } - -} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt index 9459444..6ddc8df 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt @@ -37,6 +37,21 @@ class DiagnosticExecutor: CASubCommand() { companion object{ private const val NO_DIAG_PERM = "You do not have permission to diagnostic this server" + + fun fetchNMSType(): String { + val packetManager = DependencyManager.packetManager + val packetManagerClass = packetManager.javaClass + + val result = when (packetManagerClass) { + PaperPacketManager::class.java -> "Paper NMS" + ProtocoLibWrapper::class.java -> "Protocolib" + NoPacketManager::class.java -> "None" + else -> "Version Specific" + + } + + return "$result ${if(packetManager.canSetInstantBuild) '✅' else '❌'}" + } } enum class DiagParams(val value: String) { @@ -124,7 +139,10 @@ class DiagnosticExecutor: CASubCommand() { fun diagnostic(sender: CommandSender, stb: StringBuilder, params: Set){ stb.append("Server Info\n") - stb.append("\nPlugin Version: ").append(CustomAnvil.instance.description.version) + val version = CustomAnvil.instance.description.version + stb.append("\nPlugin Version: ").append(version) + if(version.contains("dev")) stb.append(" (alpha)") + stb.append("\nLatest Update: ").append(CustomAnvil.latestVer) stb.append("\nServer Version: ").append(Bukkit.getVersion()).append(" (").append(Bukkit.getName()).append(')') stb.append("\nPlugin Enabled: ").append(if(CustomAnvil.instance.isEnabled) "Yes" else "No") @@ -181,21 +199,6 @@ class DiagnosticExecutor: CASubCommand() { simulateAnvil(player, stb, sword, enchantedBook, enchantedSword) } - private fun fetchNMSType(): String { - val packetManager = DependencyManager.packetManager - val packetManagerClass = packetManager.javaClass - - val result = when (packetManagerClass) { - PaperPacketManager::class.java -> "Paper NMS" - ProtocoLibWrapper::class.java -> "Protocolib" - NoPacketManager::class.java -> "None" - else -> "Version Specific" - - } - - return "$result ${if(packetManager.canSetInstantBuild) '✅' else '❌'}" - } - private val Plugin.pluginNameDisplay: String get() { return this.name + " v" + this.description.version diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt index 42383b6..6794af0 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt @@ -27,6 +27,7 @@ import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT import xyz.alexcrea.cuanvil.util.AnvilUseType +import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError import java.util.logging.Level object DependencyManager { @@ -141,6 +142,7 @@ object DependencyManager { "Error while trying to handle custom anvil supported plugin: ", e ) + trackError(e) // Just in case to avoid illegal items event.inventory.setItem(ANVIL_OUTPUT_SLOT, null) @@ -180,6 +182,7 @@ object DependencyManager { "Error while trying to handle custom anvil supported plugin: ", e ) + trackError(e) // Just in case to avoid illegal items event.inventory.setItem(ANVIL_OUTPUT_SLOT, null) @@ -233,6 +236,7 @@ object DependencyManager { "Error while trying to handle custom anvil supported plugin: ", e ) + trackError(e) // Just in case to avoid illegal items event.inventory.setItem(ANVIL_OUTPUT_SLOT, null) @@ -262,6 +266,7 @@ object DependencyManager { "Error while trying to handle custom anvil supported plugin: ", e ) + trackError(e) // Just in case to avoid illegal items event.inventory.setItem(ANVIL_OUTPUT_SLOT, null) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt index f014c8a..089a5fb 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/DisenchantmentDependency.kt @@ -16,6 +16,7 @@ import org.bukkit.inventory.AnvilInventory import org.bukkit.inventory.ItemStack import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener import xyz.alexcrea.cuanvil.util.AnvilXpUtil +import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError import java.util.logging.Level import kotlin.reflect.KClass @@ -38,6 +39,7 @@ class DisenchantmentDependency { Level.SEVERE, "Could not initialize disenchantment support" + "please report this bug to the developer", e ) + trackError(e) } } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt new file mode 100644 index 0000000..ad441a5 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt @@ -0,0 +1,79 @@ +package xyz.alexcrea.cuanvil.util + +import dev.faststats.bukkit.BukkitMetrics +import dev.faststats.core.ErrorTracker +import dev.faststats.core.data.Metric +import io.delilaheve.CustomAnvil +import io.delilaheve.util.ConfigOptions +import xyz.alexcrea.cuanvil.command.DiagnosticExecutor +import xyz.alexcrea.cuanvil.config.ConfigHolder + +object MetricsUtil { + + private const val BSTATS_PLUGIN_ID = 20923 + private const val FASTSTATS_TOKEN = "fc282b048adcc71a77bc00ace49e8a81" + + private var ERROR_TRACKER: ErrorTracker? = null + private var FAST_STATS_METRICS: BukkitMetrics? = null + + fun loadMetrics(plugin: CustomAnvil) { + val config = ConfigHolder.DEFAULT_CONFIG.config + val metricString = config.getString(ConfigOptions.METRIC_TYPE, MetricType.AUTO.value)!! + val metricType = MetricType.from(metricString) + + val nmsType = DiagnosticExecutor.fetchNMSType() + val isAlpha = CustomAnvil.instance.description.version.contains("dev") + if(metricType.allowBStats) { + try { + val metric = Metrics(plugin, BSTATS_PLUGIN_ID) + metric.addCustomChart(Metrics.SimplePie("nms_type") { nmsType }) + metric.addCustomChart(Metrics.SimplePie("using_alpha") { isAlpha.toString() }) + } catch (_: Exception) {} + } + + if(metricType.allowFastStats) { + val reportErrors = config.getBoolean(ConfigOptions.METRIC_COLLECT_ERROR, true) + if(reportErrors) + ERROR_TRACKER = ErrorTracker.contextAware() + + FAST_STATS_METRICS = BukkitMetrics.factory() + .addMetric(Metric.string("nms_type") { nmsType }) + .addMetric(Metric.bool("replace_too_expensive") { ConfigOptions.doReplaceTooExpensive }) + .addMetric(Metric.bool("using_alpha") { isAlpha }) + .errorTracker(ERROR_TRACKER) + .token(FASTSTATS_TOKEN) + .create(plugin) + + if(reportErrors) FAST_STATS_METRICS!!.ready() + } + } + + fun shutdownMetrics() { + FAST_STATS_METRICS?.shutdown() + } + + fun trackError(e: Throwable) { + ERROR_TRACKER?.trackError(e) + } + + fun trackError(message: String) { + ERROR_TRACKER?.trackError(message) + } +} + +enum class MetricType( + val value: String, + val allowBStats: Boolean, + val allowFastStats: Boolean, +) { + AUTO("auto", true, true), + BSTATS("bstat", true, false), + FAST_STATS("faststats", false, true), + DISABLED("disabled", false, false), + ; + + companion object { + fun from(value: String): MetricType = entries.find { it.value == value } ?: AUTO + } + +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index c1fe214..7cc1768 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,8 +1,21 @@ # -# It is recommended that you use /configanvil to edit theses config. +# It is recommended that you use /configanvil to edit most of these config. # You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! # +# What service of metric should custom anvil use +# Custom anvil collect generic information like server minecraft version, type, etc... +# It can also collect error information if error is happening (currently faststats only) +# It can also be disabled +# Please refer to README for public metric link +# Possible options: auto, bstat, faststats, disabled (auto by default) +metric_type: auto + +# Allow to report errors made caused by this plugin (only for faststats) +# This allows me to fix potentials issue that I'm not aware of +# Accept true or false (true by default) +metric_collect_errors: true + # All anvil cost will be capped to limit_repair_value if enabled. # # In other words: