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
2 changes: 2 additions & 0 deletions src/main/kotlin/xyz/atrius/waystones/Waystones.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package xyz.atrius.waystones

import org.bstats.bukkit.Metrics
import org.koin.core.annotation.KoinApplication
import org.koin.dsl.module
import org.koin.plugin.module.dsl.startKoin
Expand Down Expand Up @@ -31,6 +32,7 @@ open class Waystones : KotlinPlugin() {
modules(defaultModule())
}
koin.koin.get<WaystonesInitializer>().enable(this)
koin.koin.get<Metrics>()
}

override fun onDisable() {
Expand Down
9 changes: 0 additions & 9 deletions src/main/kotlin/xyz/atrius/waystones/config/DatabaseModule.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package xyz.atrius.waystones.config

import org.bstats.bukkit.Metrics
import org.bstats.charts.SimplePie
import org.flywaydb.core.Flyway
import org.koin.core.annotation.Module
import org.koin.core.annotation.Provided
Expand All @@ -16,7 +14,6 @@ object DatabaseModule {
@Single
fun getDatabaseConfiguration(
@Provided plugin: KotlinPlugin,
@Provided metrics: Metrics,
): DatabaseProperties {
logger.info("Attempting to load database configuration...")

Expand All @@ -26,12 +23,6 @@ object DatabaseModule {
val database = config
.getString("type")
.bindAsEnum<SupportedDatabase>()
// Track database type usage
metrics.addCustomChart(
SimplePie("database_type") {
database.description
}
)

return DatabaseProperties(
type = database,
Expand Down
158 changes: 158 additions & 0 deletions src/main/kotlin/xyz/atrius/waystones/config/MetricsModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package xyz.atrius.waystones.config

import org.bstats.bukkit.Metrics
import org.bstats.charts.AdvancedPie
import org.bstats.charts.DrilldownPie
import org.bstats.charts.SimpleBarChart
import org.bstats.charts.SimplePie
import org.bstats.charts.SingleLineChart
import org.bukkit.Material
import org.koin.core.annotation.Module
import org.koin.core.annotation.Provided
import org.koin.core.annotation.Single
import xyz.atrius.waystones.data.config.property.type.Power
import xyz.atrius.waystones.internal.KotlinPlugin
import xyz.atrius.waystones.manager.ConfigManager
import xyz.atrius.waystones.repository.WaystoneInfoRepository
import xyz.atrius.waystones.utility.bindAsEnum
import java.util.Locale
import java.util.concurrent.TimeUnit

@Module
object MetricsModule {

const val BSTATS_PLUGIN_ID: Int = 29245

private val playerCountSplits = splitsOf(5, 20, 50, 100, 200)
private val maxPlayersSplits = splitsOf(10, 25, 50, 100, 200, 500)
private val worldCountSplits = splitsOf(3, 6, 10, 20)
private val baseDistanceSplits = splitsOf(49, 99, 199, 499, 999)
private val maxBoostSplits = splitsOf(24, 49, 99, 149, 249)
private val maxWarpSizeSplits = splitsOf(24, 49, 99, 199)
private val waystoneCountSplits = splitsOf(25, 50, 100, 200, 500)

@Single
fun metrics(
@Provided plugin: KotlinPlugin,
@Provided configManager: ConfigManager,
@Provided waystoneInfoRepository: WaystoneInfoRepository,
): Metrics = Metrics(plugin, BSTATS_PLUGIN_ID).apply {
addCustomChart(SimplePie("database_type") {
plugin.config
.getString("type")
.bindAsEnum<SupportedDatabase>()
.description
})

addCustomChart(SimplePie("power_mode") {
configManager
.getPropertyOrNull<Power>("require-power")
?.value()
?.toString()
?: "INTER_DIMENSION"
})

addCustomChart(SimplePie("fallback_locale") {
configManager
.getPropertyOrNull<Locale>("fallback-locale")
?.value()
?.getDisplayLanguage(Locale.ENGLISH)
?: "English"
})

addCustomChart(SimpleBarChart("feature_adoption") {
mapOf(
"Portal Sickness" to configManager.booleanFlag("enable-portal-sickness"),
"Single-Use Keys" to configManager.booleanFlag("single-use"),
"Uses Custom Recipe" to configManager.customRecipeFlag("key-recipe"),
)
})

addCustomChart(DrilldownPie("player_count") {
drilldown(plugin.server.onlinePlayers.size, playerCountSplits)
})

addCustomChart(DrilldownPie("max_players") {
drilldown(plugin.server.maxPlayers, maxPlayersSplits)
})

addCustomChart(DrilldownPie("world_count") {
drilldown(plugin.server.worlds.size, worldCountSplits)
})

addCustomChart(DrilldownPie("base_distance") {
drilldown(configManager.intProperty("base-distance"), baseDistanceSplits)
})

addCustomChart(DrilldownPie("max_boost") {
drilldown(configManager.intProperty("max-boost"), maxBoostSplits)
})

addCustomChart(DrilldownPie("max_warp_size") {
drilldown(configManager.intProperty("max-warp-size"), maxWarpSizeSplits)
})

addCustomChart(AdvancedPie("world_environments") {
plugin.server.worlds
.groupBy { it.environment.name }
.mapValues { it.value.size }
})

addCustomChart(SingleLineChart("waystone_count") {
waystoneInfoRepository.entries().get(1, TimeUnit.SECONDS)
})

addCustomChart(DrilldownPie("waystone_count_bucketed") {
drilldown(waystoneInfoRepository.entries().get(1, TimeUnit.SECONDS), waystoneCountSplits)
})
}

private class Splits(private val points: IntArray) {

fun resolve(value: Int): String {
for (i in points.indices) {
// Skip all buckets where the current end point is less than the input value
if (value > points[i]) {
continue
}
// Cap lower end at 0, otherwise get the value of the previous point in line and add 1
val start = when {
i <= 0 -> 0
else -> points[i - 1] + 1
}
// Get the value of the current point and construct the range
return "$start-${points[i]}"
}
// Default case, anything over the max of all buckets
return "${points.last() + 1}+"
}
}

private fun splitsOf(vararg points: Int) = Splits(intArrayOf(*points))

private fun drilldown(value: Int, splits: Splits): Map<String, Map<String, Int>> =
mapOf(splits.resolve(value) to mapOf(value.toString() to 1))

private fun ConfigManager.booleanFlag(key: String): Int = when (
getPropertyOrNull<Boolean>(key)?.value()
) {
true -> 1
else -> 0
}

private fun ConfigManager.intProperty(key: String): Int =
getPropertyOrNull<Int>(key)
?.value()
?: 0

private fun ConfigManager.customRecipeFlag(key: String): Int {
val prop = getListPropertyOrNull<List<Material>>(key)
?: return 0
// If the lists have equality, then its assumed the recipe has not changed
if (prop.value() == prop.default) {
return 0
}

return 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@ package xyz.atrius.waystones.config
import com.google.gson.FieldNamingPolicy
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import org.bstats.bukkit.Metrics
import org.bukkit.Material
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Module
import org.koin.core.annotation.Named
import org.koin.core.annotation.Provided
import org.koin.core.annotation.Single
import xyz.atrius.waystones.data.json.serializer.MaterialTypeAdapter
import xyz.atrius.waystones.internal.KotlinPlugin
import java.util.Locale

const val BSTATS_PLUGIN_ID: Int = 29245

@Module
@ComponentScan("xyz.atrius.waystones")
object WaystonesModule {
Expand All @@ -37,8 +32,4 @@ object WaystonesModule {
@Single
@Named("defaultPluginLocale")
fun defaultPluginLocale(): Locale = Locale.ENGLISH

@Single(createdAtStart = true)
fun metrics(@Provided plugin: KotlinPlugin): Metrics =
Metrics(plugin, BSTATS_PLUGIN_ID)
}
Loading