Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: folia support #98

Open
wants to merge 11 commits into
base: dev/0.3.x
Choose a base branch
from
4 changes: 2 additions & 2 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Configure GPG Key
run: echo "${{secrets.SIGNING_KEY}}" | base64 --decode > /tmp/keyring.gpg
- name: Set up JDK 17
Expand Down Expand Up @@ -35,7 +35,7 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Configure GPG Key
run: echo "${{secrets.SIGNING_KEY}}" | base64 --decode > /tmp/keyring.gpg
- name: Set up JDK 17
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Configure GPG Key
run: echo "${{secrets.SIGNING_KEY}}" | base64 --decode > /tmp/keyring.gpg
- name: Set up JDK 17
Expand All @@ -34,7 +34,7 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Configure GPG Key
run: echo "${{secrets.SIGNING_KEY}}" | base64 --decode > /tmp/keyring.gpg
- name: Set up JDK 17
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ UnifiedMetrics is a fully-featured free and open-source metrics collection plugi
licensed under [GNU LGPLv3](COPYING.LESSER).

[![Grafana Dashboard](.github/assets/grafana.png)](https://unifiedmetrics-demo.cubxity.dev)
*Dashboard [included](https://github.com/Cubxity/UnifiedMetrics/wiki/Grafana) out-of-box!*
*Dashboard [included](https://docs.cubxity.dev/docs/unifiedmetrics/guides/grafana) out-of-box!*
Click [here](https://unifiedmetrics-demo.cubxity.dev) for live preview!

## Features
Expand Down Expand Up @@ -37,15 +37,15 @@ Click [here](https://unifiedmetrics-demo.cubxity.dev) for live preview!

## Getting started

Read the [wiki](https://github.com/Cubxity/UnifiedMetrics/wiki) for instructions on how to get started.
Read the [wiki](https://docs.cubxity.dev/docs/unifiedmetrics/intro) for instructions on how to get started.

## Metrics

<details>
<summary>Table of metrics (click to show)</summary>

| Collector | Description | Platform | Default |
|---------------|-------------------------------------------------|------------------|---------|
| ------------- | ----------------------------------------------- | ---------------- | ------- |
| systemGc | Garbage collection duration and freed bytes | All | true |
| systemMemory | Memory used, committed, max and init | All | true |
| systemProcess | CPU load, seconds, and process start time | All | true |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ data class UnifiedMetricsCollectorsConfig(
val server: Boolean = true,
val world: Boolean = true,
val tick: Boolean = true,
val events: Boolean = true
val events: Boolean = true,
val regionizedServer: Boolean = true
)

private fun env(name: String, default: String): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,12 @@ object Metrics {
const val WorldPlayersCount = "minecraft_world_players_count"
const val WorldLoadedChunks = "minecraft_world_loaded_chunks"
}

object RegionizedServer {
const val RegionCount = "minecraft_regionized_region_count"
const val RegionTick = "minecraft_regionized_region_tick_total"
const val RegionEntitiesCount = "minecraft_regionized_region_entities_count"
const val RegionPlayersCount = "minecraft_regionized_region_players_count"
const val RegionChunksCount = "minecraft_regionized_region_chunks_count"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package dev.cubxity.plugins.metrics.common.metric.system.thread

import dev.cubxity.plugins.metrics.api.metric.collector.Collector
import dev.cubxity.plugins.metrics.api.metric.collector.NANOSECONDS_PER_SECOND
import dev.cubxity.plugins.metrics.api.metric.data.CounterMetric
import dev.cubxity.plugins.metrics.api.metric.data.GaugeMetric
import dev.cubxity.plugins.metrics.api.metric.data.Metric
Expand All @@ -26,10 +27,29 @@ import java.lang.management.ManagementFactory
class ThreadCollector : Collector {
private val bean = ManagementFactory.getThreadMXBean()

override fun collect(): List<Metric> = listOf(
GaugeMetric("jvm_threads_current_count", value = bean.threadCount),
GaugeMetric("jvm_threads_daemon_count", value = bean.daemonThreadCount),
CounterMetric("jvm_threads_started_total", value = bean.totalStartedThreadCount),
GaugeMetric("jvm_threads_peak", value = bean.peakThreadCount),
)
override fun collect(): List<Metric> {
val ids = bean.allThreadIds
val list = ArrayList<Metric>(4 + 2 * ids.size)

list += GaugeMetric("jvm_threads_current_count", value = bean.threadCount)
list += GaugeMetric("jvm_threads_daemon_count", value = bean.daemonThreadCount)
list += CounterMetric("jvm_threads_started_total", value = bean.totalStartedThreadCount)
list += GaugeMetric("jvm_threads_peak", value = bean.peakThreadCount)

ids.forEach { id ->
val info = bean.getThreadInfo(id) ?: return@forEach
val labels = mapOf("thread" to info.threadName)
list += CounterMetric(
"jvm_threads_cpu_time_total",
value = bean.getThreadCpuTime(id) / NANOSECONDS_PER_SECOND,
labels = labels
)
list += CounterMetric(
"jvm_threads_user_time_total",
value = bean.getThreadUserTime(id) / NANOSECONDS_PER_SECOND,
labels = labels
)
}
return list
}
}
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
14 changes: 7 additions & 7 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,15 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
Expand Down Expand Up @@ -202,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.

set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Expand Down
12 changes: 11 additions & 1 deletion platforms/bukkit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@

plugins {
id("com.github.johnrengelman.shadow")
id("io.papermc.paperweight.userdev") version "1.5.3"
}

repositories {
maven("https://papermc.io/repo/repository/maven-public/")
mavenLocal()
}

dependencies {
api(project(":unifiedmetrics-core"))
compileOnly("com.destroystokyo.paper", "paper-api", "1.16.5-R0.1-SNAPSHOT")
// compileOnly("com.destroystokyo.paper", "paper-api", "1.16.5-R0.1-SNAPSHOT")
paperweight.devBundle("dev.folia", "1.20.1-R0.1-SNAPSHOT")
}

tasks {
assemble {
dependsOn(reobfJar)
}
shadowJar {
archiveClassifier.set("")
relocate("retrofit2", "dev.cubxity.plugins.metrics.libs.retrofit2")
Expand All @@ -46,3 +52,7 @@ tasks {
}
}
}

java {
disableAutoTargetJvm()
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package dev.cubxity.plugins.metrics.bukkit

import io.papermc.paper.threadedregions.RegionizedServer
import kotlinx.coroutines.*
import org.bukkit.Bukkit
import org.bukkit.plugin.java.JavaPlugin
Expand Down Expand Up @@ -47,4 +48,15 @@ class BukkitDispatcher(private val plugin: JavaPlugin) : CoroutineDispatcher(),
plugin.server.scheduler.runTask(plugin, block)
}
}
}
}

@OptIn(InternalCoroutinesApi::class)
class FoliaDispatcher : CoroutineDispatcher(), Delay {
override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
TODO("Not yet implemented")
}

override fun dispatch(context: CoroutineContext, block: Runnable) {
RegionizedServer.getInstance().addTask(block)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@ package dev.cubxity.plugins.metrics.bukkit
import dev.cubxity.plugins.metrics.api.UnifiedMetrics
import dev.cubxity.plugins.metrics.bukkit.bootstrap.UnifiedMetricsBukkitBootstrap
import dev.cubxity.plugins.metrics.bukkit.metric.events.EventsCollection
import dev.cubxity.plugins.metrics.bukkit.metric.regionized.FoliaRegionCollection
import dev.cubxity.plugins.metrics.bukkit.metric.server.ServerCollection
import dev.cubxity.plugins.metrics.bukkit.metric.tick.TickCollection
import dev.cubxity.plugins.metrics.bukkit.metric.world.WorldCollection
import dev.cubxity.plugins.metrics.bukkit.util.BukkitPlatform
import dev.cubxity.plugins.metrics.core.plugin.CoreUnifiedMetricsPlugin
import org.bukkit.plugin.ServicePriority
import java.util.concurrent.Executors

class UnifiedMetricsBukkitPlugin(
override val bootstrap: UnifiedMetricsBukkitBootstrap
override val bootstrap: UnifiedMetricsBukkitBootstrap
) : CoreUnifiedMetricsPlugin() {
private val executor = Executors.newScheduledThreadPool(1)

Expand All @@ -50,6 +52,10 @@ class UnifiedMetricsBukkitPlugin(
if (world) registerCollection(WorldCollection(bootstrap))
if (tick) registerCollection(TickCollection(bootstrap))
if (events) registerCollection(EventsCollection(bootstrap))

if (regionizedServer && BukkitPlatform.current == BukkitPlatform.Folia) {
registerCollection(FoliaRegionCollection())
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ package dev.cubxity.plugins.metrics.bukkit.bootstrap

import dev.cubxity.plugins.metrics.api.platform.PlatformType
import dev.cubxity.plugins.metrics.bukkit.BukkitDispatcher
import dev.cubxity.plugins.metrics.bukkit.FoliaDispatcher
import dev.cubxity.plugins.metrics.bukkit.UnifiedMetricsBukkitPlugin
import dev.cubxity.plugins.metrics.bukkit.util.BukkitPlatform
import dev.cubxity.plugins.metrics.common.UnifiedMetricsBootstrap
import dev.cubxity.plugins.metrics.common.plugin.logger.JavaLogger
import kotlinx.coroutines.CoroutineDispatcher
Expand Down Expand Up @@ -47,9 +49,13 @@ class UnifiedMetricsBukkitBootstrap : JavaPlugin(), UnifiedMetricsBootstrap {

override val logger = JavaLogger(getLogger())

override val dispatcher: CoroutineDispatcher = BukkitDispatcher(this)
override val dispatcher: CoroutineDispatcher = when (BukkitPlatform.current) {
BukkitPlatform.Folia -> FoliaDispatcher()
else -> BukkitDispatcher(this)
}

override fun onEnable() {
(this as UnifiedMetricsBootstrap).logger.info("Running on Bukkit platform ${BukkitPlatform.current}")
plugin.enable()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* This file is part of UnifiedMetrics.
*
* UnifiedMetrics is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UnifiedMetrics is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with UnifiedMetrics. If not, see <https://www.gnu.org/licenses/>.
*/

package dev.cubxity.plugins.metrics.bukkit.metric.regionized

import dev.cubxity.plugins.metrics.api.metric.collector.Collector
import dev.cubxity.plugins.metrics.api.metric.collector.CollectorCollection

class FoliaRegionCollection : CollectorCollection {
override val collectors: List<Collector> = listOf(FoliaRegionCollector())
override val isAsync: Boolean
get() = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* This file is part of UnifiedMetrics.
*
* UnifiedMetrics is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UnifiedMetrics is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with UnifiedMetrics. If not, see <https://www.gnu.org/licenses/>.
*/

package dev.cubxity.plugins.metrics.bukkit.metric.regionized

import dev.cubxity.plugins.metrics.api.metric.collector.Collector
import dev.cubxity.plugins.metrics.api.metric.data.CounterMetric
import dev.cubxity.plugins.metrics.api.metric.data.GaugeMetric
import dev.cubxity.plugins.metrics.api.metric.data.Metric
import dev.cubxity.plugins.metrics.bukkit.util.regioniser
import dev.cubxity.plugins.metrics.common.metric.Metrics
import io.papermc.paper.threadedregions.ThreadedRegionizer.ThreadedRegion
import io.papermc.paper.threadedregions.TickRegions.TickRegionData
import io.papermc.paper.threadedregions.TickRegions.TickRegionSectionData
import org.bukkit.Bukkit


class FoliaRegionCollector : Collector {
override fun collect(): List<Metric> {
val worlds = Bukkit.getWorlds()

val regions = ArrayList<ThreadedRegion<TickRegionData, TickRegionSectionData>>()
for (world in worlds) {
world.regioniser.computeForAllRegions(regions::add)
}

val samples = ArrayList<Metric>(regions.size * 4 + 1)
for (region in regions) {
val tags = mapOf("world" to region.data.world.serverLevelData.levelName, "region" to "${region.id}")
samples.add(CounterMetric(Metrics.RegionizedServer.RegionTick, tags, region.data.currentTick))

val stats = region.data.regionStats
samples.add(GaugeMetric(Metrics.RegionizedServer.RegionEntitiesCount, tags, stats.entityCount))
samples.add(GaugeMetric(Metrics.RegionizedServer.RegionPlayersCount, tags, stats.playerCount))
samples.add(GaugeMetric(Metrics.RegionizedServer.RegionChunksCount, tags, stats.chunkCount))
}

samples.add(GaugeMetric(Metrics.RegionizedServer.RegionCount, value = regions.size))

return samples
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ import dev.cubxity.plugins.metrics.api.metric.collector.Histogram
import dev.cubxity.plugins.metrics.api.metric.store.VolatileDoubleStore
import dev.cubxity.plugins.metrics.api.metric.store.VolatileLongStore
import dev.cubxity.plugins.metrics.bukkit.bootstrap.UnifiedMetricsBukkitBootstrap
import dev.cubxity.plugins.metrics.bukkit.util.classExists
import dev.cubxity.plugins.metrics.bukkit.util.BukkitPlatform
import dev.cubxity.plugins.metrics.common.metric.Metrics

class TickCollection(bootstrap: UnifiedMetricsBukkitBootstrap) : CollectorCollection {
private val reporter = if (classExists("com.destroystokyo.paper.event.server.ServerTickStartEvent")) {
PaperTickReporter(this, bootstrap)
} else {
BukkitTickReporter(this, bootstrap)
private val reporter = when (BukkitPlatform.current) {
BukkitPlatform.Folia, BukkitPlatform.Paper -> PaperTickReporter(this, bootstrap)
else -> BukkitTickReporter(this, bootstrap)
}

// The callback is called from a single thread
Expand Down
Loading