Skip to content

Commit 9f809c6

Browse files
authored
Merge pull request #18 from renvins/dev/velocity
Implement velocity module and provisioned dashboards
2 parents ddc7a9a + 9d796ed commit 9f809c6

36 files changed

+2777
-391
lines changed

.github/workflows/ci.yml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,25 @@ jobs:
3333
- name: Setup Gradle and Build Plugin Jar
3434
uses: gradle/actions/setup-gradle@v4 # Use v4 or latest stable version
3535

36-
# Gradle with the new updates doesn't support arguments
37-
- name: Build jar
36+
# Build both Bukkit and Velocity JARs
37+
- name: Build JAR files
3838
run: ./gradlew shadowJar
3939

40-
# Upload JAR as an artifact (NEW STEP)
41-
- name: Upload JAR Artifact
40+
# Upload Bukkit JAR as an artifact
41+
- name: Upload Bukkit JAR Artifact
4242
uses: actions/upload-artifact@v4
4343
with:
44-
name: plugin-jar
45-
path: bukkit/build/libs/*.jar # Adjust this path to match your JAR location
44+
name: serverpulse-bukkit-jar
45+
path: bukkit/build/libs/*.jar
46+
retention-days: 14 # Keep artifacts for 14 days
47+
if-no-files-found: error # Fail the workflow if no JARs are found
48+
49+
# Upload Velocity JAR as an artifact
50+
- name: Upload Velocity JAR Artifact
51+
uses: actions/upload-artifact@v4
52+
with:
53+
name: serverpulse-velocity-jar
54+
path: velocity/build/libs/*.jar
4655
retention-days: 14 # Keep artifacts for 14 days
4756
if-no-files-found: error # Fail the workflow if no JARs are found
4857

@@ -53,7 +62,6 @@ jobs:
5362
run: sudo apt-get update && sudo apt-get install -y jq
5463

5564
# 5. Start Docker Compose services in detached mode
56-
# Replace 'path/to/your/docker-compose.yml' if it's not in the root
5765
- name: Start Docker Infrastructure
5866
run: docker compose -f infra/docker-compose.yml up -d
5967

.github/workflows/create_release.yml

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Create Release Asset
1+
name: Create Release Assets
22

33
# Trigger the workflow only when a release is published
44
on:
@@ -36,9 +36,9 @@ jobs:
3636
- name: Build jar
3737
run: ./gradlew shadowJar
3838

39-
# 5. Find the specific Shadow Jar file and extract its name
40-
- name: Find Shadow Jar and Extract Name
41-
id: find_jar
39+
# 5. Find the Bukkit Shadow Jar file and extract its name
40+
- name: Find Bukkit Shadow Jar and Extract Name
41+
id: find_bukkit_jar
4242
run: |
4343
JAR_PATH=$(find bukkit/build/libs -maxdepth 1 -name '*.jar' -printf "%s %p\n" | sort -nr | head -n 1 | awk '{print $2}')
4444
if [ -z "$JAR_PATH" ]; then
@@ -52,12 +52,38 @@ jobs:
5252
echo "filename=$JAR_FILENAME" >> $GITHUB_OUTPUT
5353
shell: bash
5454

55-
# 6. Upload the Shadow Jar as a release asset
56-
- name: Upload Release Asset
55+
# 6. Find the Velocity Shadow Jar file and extract its name
56+
- name: Find Velocity Shadow Jar and Extract Name
57+
id: find_velocity_jar
58+
run: |
59+
JAR_PATH=$(find velocity/build/libs -maxdepth 1 -name '*.jar' -printf "%s %p\n" | sort -nr | head -n 1 | awk '{print $2}')
60+
if [ -z "$JAR_PATH" ]; then
61+
echo "Error: Could not find the shadow JAR file in velocity/build/libs/"
62+
exit 1
63+
fi
64+
JAR_FILENAME=$(basename "$JAR_PATH")
65+
echo "Found JAR path: $JAR_PATH"
66+
echo "Found JAR filename: $JAR_FILENAME"
67+
echo "path=$JAR_PATH" >> $GITHUB_OUTPUT
68+
echo "filename=$JAR_FILENAME" >> $GITHUB_OUTPUT
69+
shell: bash
70+
71+
# 7. Upload the Bukkit Shadow Jar as a release asset
72+
- name: Upload Bukkit Release Asset
5773
uses: svenstaro/upload-release-action@v2
5874
with:
5975
repo_token: ${{ secrets.GITHUB_TOKEN }} # Provided by GitHub Actions automatically
60-
file: ${{ steps.find_jar.outputs.path }} # The path to the JAR found in the previous step
61-
asset_name: ${{ steps.find_jar.outputs.filename }} # Use the filename extracted earlier
76+
file: ${{ steps.find_bukkit_jar.outputs.path }} # The path to the JAR found in the previous step
77+
asset_name: ${{ steps.find_bukkit_jar.outputs.filename }} # Use the filename extracted earlier
6278
tag: ${{ github.ref }} # The git tag associated with the release that triggered the workflow
6379
overwrite: true # Optional: Replace asset with the same name if it already exists
80+
81+
# 8. Upload the Velocity Shadow Jar as a release asset
82+
- name: Upload Velocity Release Asset
83+
uses: svenstaro/upload-release-action@v2
84+
with:
85+
repo_token: ${{ secrets.GITHUB_TOKEN }} # Provided by GitHub Actions automatically
86+
file: ${{ steps.find_velocity_jar.outputs.path }} # The path to the JAR found in the previous step
87+
asset_name: ${{ steps.find_velocity_jar.outputs.filename }} # Use the filename extracted earlier
88+
tag: ${{ github.ref }} # The git tag associated with the release that triggered the workflow
89+
overwrite: true # Optional: Replace asset with the same name if it already exists

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ ServerPulse is an **open-source**, real-time performance monitoring tool for Min
1313
![ServerPulse Grafana Dashboard Example2](img/dashboard2.png)
1414
*Example dashboard view 2: Per-World Details*
1515

16+
![ServerPulse Grafana Dashboard Example3](img/dashboard3.png)
17+
*Example dashboard view 3: Players Ping Overview*
18+
1619
</details>
1720

1821
## 📖 What This Project Is
@@ -30,6 +33,7 @@ ServerPulse now supports **all Minecraft server platforms** in the Bukkit ecosys
3033

3134
- **Bukkit/Spigot**: Full support with custom TPS monitoring implementation
3235
- **Paper and its forks** (Purpur, Pufferfish, etc.): Enhanced support with native TPS monitoring
36+
- **Velocity**: Support for Velocity proxy servers (ofc TPS and world metrics are not available)
3337

3438
The plugin automatically detects your server platform and uses the most efficient implementation available for that environment.
3539

@@ -38,7 +42,7 @@ The plugin automatically detects your server platform and uses the most efficien
3842
ServerPulse isn't just another metrics exporter - it offers several unique advantages:
3943

4044
- **Complete Monitoring Stack** - Fully integrated solution with InfluxDB (optimized for time-series data) and pre-configured Grafana dashboards
41-
- **Universal Platform Support** - Works with any Bukkit-based server while taking advantage of Paper-specific optimizations when available
45+
- **Universal Platform Support** - Works with any Bukkit-based and Velocity server while taking advantage of Paper-specific optimizations when available
4246
- **Per-World Analytics** - Track entity counts, chunk loading, and performance metrics separately for each world
4347
- **Flexible Tagging System** - Group and filter metrics by server, network, region, or any custom dimension through simple configuration
4448
- **Zero-Configuration Dashboards** - Auto-provisioned Grafana dashboards - no manual setup required

api/src/main/java/it/renvins/serverpulse/api/ServerPulseAPI.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ public interface ServerPulseAPI {
2626
* Retrieves the instance of ITPSRetriever.
2727
*
2828
* @return The ITPSRetriever instance.
29+
* @throws UnsupportedOperationException if the API implementation does not support TPS retrieval.
2930
*/
30-
ITPSRetriever getTPSRetriever();
31+
default ITPSRetriever getTPSRetriever() {
32+
throw new UnsupportedOperationException("TPSRetriever is not supported in this API implementation.");
33+
}
3134

3235
/**
3336
* Retrieves the instance of IDiskRetriever.

api/src/main/java/it/renvins/serverpulse/api/metrics/ITPSRetriever.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,13 @@
22

33
public interface ITPSRetriever {
44

5-
double[] getTPS();
5+
/**
6+
* Retrieves the TPS (Ticks Per Second) of the server.
7+
*
8+
* @return an array of doubles representing the TPS values.
9+
* The first value is the average TPS over the last minute,
10+
* the second value is the average TPS over the last 5 minutes,
11+
* and the third value is the average TPS over the last 15 minutes.
12+
*/
13+
double[] getTPS();
614
}

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
group = "it.renvins"
2-
version = "0.2.2-SNAPSHOT"
2+
version = "0.2.5-SNAPSHOT"
33

44
repositories {
55
mavenCentral()

bukkit/src/main/java/it/renvins/serverpulse/bukkit/ServerPulseBukkitLoader.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@
99
import it.renvins.serverpulse.api.service.IDatabaseService;
1010
import it.renvins.serverpulse.api.service.IMetricsService;
1111
import it.renvins.serverpulse.api.service.Service;
12+
import it.renvins.serverpulse.bukkit.logger.BukkitLogger;
1213
import it.renvins.serverpulse.bukkit.metrics.BukkitTPSRetriever;
1314
import it.renvins.serverpulse.common.DatabaseService;
1415
import it.renvins.serverpulse.common.config.DatabaseConfiguration;
1516
import it.renvins.serverpulse.common.config.MetricsConfiguration;
1617
import it.renvins.serverpulse.bukkit.commands.ServerPulseCommand;
1718
import it.renvins.serverpulse.bukkit.config.BukkitConfiguration;
19+
import it.renvins.serverpulse.common.logger.PulseLogger;
1820
import it.renvins.serverpulse.common.metrics.DiskRetriever;
1921
import it.renvins.serverpulse.bukkit.config.BukkitDatabaseConfiguration;
2022
import it.renvins.serverpulse.bukkit.config.BukkitMetricsConfiguration;
21-
import it.renvins.serverpulse.bukkit.metrics.PingRetriever;
23+
import it.renvins.serverpulse.bukkit.metrics.BukkitPingRetriever;
2224
import it.renvins.serverpulse.bukkit.metrics.PaperTPSRetriever;
2325
import it.renvins.serverpulse.bukkit.platform.BukkitPlatform;
2426
import it.renvins.serverpulse.bukkit.scheduler.BukkitTaskScheduler;
@@ -31,9 +33,6 @@ public class ServerPulseBukkitLoader implements Service {
3133

3234
private final BukkitConfiguration config;
3335

34-
private final BukkitPlatform platform;
35-
private final BukkitTaskScheduler taskScheduler;
36-
3736
private final IDatabaseService databaseService;
3837
private final IMetricsService metricsService;
3938

@@ -47,22 +46,24 @@ public ServerPulseBukkitLoader(ServerPulseBukkit plugin) {
4746

4847
this.config = new BukkitConfiguration(plugin, "config.yml");
4948

50-
this.platform = new BukkitPlatform(plugin);
51-
this.taskScheduler = new BukkitTaskScheduler(plugin);
49+
PulseLogger logger = new BukkitLogger(LOGGER);
50+
51+
BukkitPlatform platform = new BukkitPlatform(plugin);
52+
BukkitTaskScheduler taskScheduler = new BukkitTaskScheduler(plugin);
5253

5354
DatabaseConfiguration databaseConfiguration = new BukkitDatabaseConfiguration(config);
5455
MetricsConfiguration metricsConfiguration = new BukkitMetricsConfiguration(config);
5556

56-
this.databaseService = new DatabaseService(LOGGER, platform, databaseConfiguration, taskScheduler);
57-
this.metricsService = new MetricsService(LOGGER, platform, metricsConfiguration, taskScheduler);
57+
this.databaseService = new DatabaseService(logger, platform, databaseConfiguration, taskScheduler);
58+
this.metricsService = new MetricsService(logger, platform, metricsConfiguration, taskScheduler);
5859

5960
if (isPaper()) {
6061
this.tpsRetriever = new PaperTPSRetriever();
6162
} else {
6263
this.tpsRetriever = new BukkitTPSRetriever(plugin);
6364
}
6465
this.diskRetriever = new DiskRetriever(plugin.getDataFolder());
65-
this.pingRetriever = new PingRetriever();
66+
this.pingRetriever = new BukkitPingRetriever();
6667
}
6768

6869
@Override
@@ -76,6 +77,8 @@ public void load() {
7677

7778
return;
7879
}
80+
ServerPulseProvider.register(new ServerPulseBukkitAPI(databaseService, metricsService, tpsRetriever, diskRetriever, pingRetriever));
81+
7982
databaseService.load();
8083
if (!plugin.isEnabled()) {
8184
return;
@@ -88,7 +91,6 @@ public void load() {
8891
}
8992

9093
plugin.getCommand("serverpulse").setExecutor(new ServerPulseCommand(config));
91-
ServerPulseProvider.register(new ServerPulseBukkitAPI(databaseService, metricsService, tpsRetriever, diskRetriever, pingRetriever));
9294
}
9395

9496
@Override
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package it.renvins.serverpulse.bukkit.logger;
2+
3+
import java.util.logging.Level;
4+
import java.util.logging.Logger;
5+
6+
import it.renvins.serverpulse.common.logger.PulseLogger;
7+
import lombok.RequiredArgsConstructor;
8+
9+
@RequiredArgsConstructor
10+
public class BukkitLogger implements PulseLogger {
11+
12+
private final Logger logger;
13+
14+
@Override
15+
public void info(String message) {
16+
logger.info(message);
17+
}
18+
19+
@Override
20+
public void warning(String message) {
21+
logger.warning(message);
22+
}
23+
24+
@Override
25+
public void error(String message) {
26+
logger.severe(message);
27+
}
28+
29+
@Override
30+
public void error(String message, Throwable throwable) {
31+
logger.log(Level.SEVERE, message, throwable);
32+
}
33+
}

bukkit/src/main/java/it/renvins/serverpulse/bukkit/metrics/PingRetriever.java renamed to bukkit/src/main/java/it/renvins/serverpulse/bukkit/metrics/BukkitPingRetriever.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import org.bukkit.Bukkit;
55
import org.bukkit.entity.Player;
66

7-
public class PingRetriever implements IPingRetriever {
7+
public class BukkitPingRetriever implements IPingRetriever {
88

99
@Override
1010
public int getMinPing() {

0 commit comments

Comments
 (0)