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
37 changes: 22 additions & 15 deletions core/src/main/java/dev/faststats/core/SimpleMetrics.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,6 @@
import static java.nio.charset.StandardCharsets.UTF_8;

public abstract class SimpleMetrics implements Metrics {
protected static final String ONBOARDING_MESSAGE = """
This plugin uses FastStats to collect anonymous usage statistics.
No personal or identifying information is ever collected.
To opt out, set 'enabled=false' in the metrics configuration file.
Learn more at: https://faststats.dev/info

Since this is your first start with FastStats, metrics submission will not start
until you restart the server to allow you to opt out if you prefer.""";

private final HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(3))
.version(HttpClient.Version.HTTP_1_1)
Expand Down Expand Up @@ -99,6 +90,17 @@ protected SimpleMetrics(Config config, Set<Chart<?>> charts, @Token String token
this.url = url;
}

protected String getOnboardingMessage() {
return """
This plugin uses FastStats to collect anonymous usage statistics.
No personal or identifying information is ever collected.
To opt out, set 'enabled=false' in the metrics configuration file.
Learn more at: https://faststats.dev/info

Since this is your first start with FastStats, metrics submission will not start
until you restart the server to allow you to opt out if you prefer.""";
}

protected long getInitialDelay() {
return TimeUnit.SECONDS.toMillis(Long.getLong("faststats.initial-delay", 30));
}
Expand All @@ -121,12 +123,16 @@ private void startSubmitting(long initialDelay, long period, TimeUnit unit) {

if (config.firstRun) {

printInfo("-".repeat(80));
for (var s : ONBOARDING_MESSAGE.split("\n")) printInfo(s);
printInfo("-".repeat(80));
var separatorLength = 0;
var split = getOnboardingMessage().split("\n");
for (var s : split) if (s.length() > separatorLength) separatorLength = s.length();

printInfo("-".repeat(separatorLength));
for (var s : split) printInfo(s);
printInfo("-".repeat(separatorLength));

System.setProperty("faststats.first-run", "true");
return;
if (!config.externallyManaged()) return;
}

var enabled = Boolean.parseBoolean(System.getProperty("faststats.enabled", "true"));
Expand Down Expand Up @@ -350,7 +356,8 @@ public record Config(
boolean debug,
boolean enabled,
boolean errorTracking,
boolean firstRun
boolean firstRun,
boolean externallyManaged
) implements Metrics.Config {

public static final String DEFAULT_COMMENT = """
Expand Down Expand Up @@ -413,7 +420,7 @@ public static Config read(Path file, String comment, boolean externallyManaged,
throw new RuntimeException("Failed to save metrics config", e);
}

return new Config(serverId, additionalMetrics, debug, enabled, errorTracking, firstRun);
return new Config(serverId, additionalMetrics, debug, enabled, errorTracking, firstRun, externallyManaged);
}

private static Optional<Properties> readOrEmpty(Path file) throws RuntimeException {
Expand Down
2 changes: 1 addition & 1 deletion core/src/test/java/dev/faststats/MockMetrics.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@NullMarked
public class MockMetrics extends SimpleMetrics {
public MockMetrics(UUID serverId, @Token String token, @Nullable ErrorTracker tracker, boolean debug) {
super(new Config(serverId, true, debug, true, true, false), Set.of(), token, tracker, URI.create("http://localhost:5000/v1/collect"), debug);
super(new Config(serverId, true, debug, true, true, false, false), Set.of(), token, tracker, URI.create("http://localhost:5000/v1/collect"), debug);
}

@Override
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ include("hytale:example-plugin")
include("minestom")
include("nukkit")
include("sponge")
include("sponge:example-plugin")
include("velocity")
13 changes: 13 additions & 0 deletions sponge/example-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
repositories {
maven("https://repo.spongepowered.org/repository/maven-public/")
}

dependencies {
compileOnly("org.spongepowered:spongeapi:8.0.0")
implementation(project(":sponge"))
}

tasks.shadowJar {
// optionally relocate faststats
relocate("dev.faststats", "com.example.utils.faststats")
}
68 changes: 68 additions & 0 deletions sponge/example-plugin/src/main/java/com/example/ExamplePlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.example;

import com.google.inject.Inject;
import dev.faststats.core.ErrorTracker;
import dev.faststats.core.Metrics;
import dev.faststats.core.chart.Chart;
import dev.faststats.sponge.SpongeMetrics;
import org.jspecify.annotations.Nullable;
import org.spongepowered.api.Server;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.lifecycle.StartedEngineEvent;
import org.spongepowered.api.event.lifecycle.StoppingEngineEvent;
import org.spongepowered.plugin.PluginContainer;
import org.spongepowered.plugin.builtin.jvm.Plugin;


@Plugin("example")
public class ExamplePlugin {
// context-aware error tracker, automatically tracks errors in the same class loader
public static final ErrorTracker ERROR_TRACKER = ErrorTracker.contextAware();

// context-unaware error tracker, does not automatically track errors
public static final ErrorTracker CONTEXT_UNAWARE_ERROR_TRACKER = ErrorTracker.contextUnaware();

private @Inject PluginContainer pluginContainer;
private @Inject SpongeMetrics.Factory factory;

private @Nullable Metrics metrics = null;

@Listener
public void onServerStart(final StartedEngineEvent<Server> event) {
this.metrics = factory
// .url(URI.create("https://metrics.example.com/v1/collect")) // For self-hosted metrics servers only

// Custom example charts
// For this to work you have to create a corresponding data source in your project settings first
.addChart(Chart.number("example_chart", () -> 42))
.addChart(Chart.string("example_string", () -> "Hello, World!"))
.addChart(Chart.bool("example_boolean", () -> true))
.addChart(Chart.stringArray("example_string_array", () -> new String[]{"Option 1", "Option 2"}))
.addChart(Chart.numberArray("example_number_array", () -> new Number[]{1, 2, 3}))
.addChart(Chart.booleanArray("example_boolean_array", () -> new Boolean[]{true, false}))

// Attach an error tracker
// This must be enabled in the project settings
.errorTracker(ERROR_TRACKER)

//.debug(true) // Enable debug mode for development and testing

.token("bafe240e8d1a4b919e5083928539799d") // required -> token can be found in the settings of your project
.create(pluginContainer);
ERROR_TRACKER.trackError(new RuntimeException("Something went wrong!", new Exception("Cause")));
}

@Listener
public void onServerStop(final StoppingEngineEvent<Server> event) {
if (metrics != null) metrics.shutdown();
}

public void doSomethingWrong() {
try {
// Do something that might throw an error
throw new RuntimeException("Something went wrong!");
} catch (Exception e) {
CONTEXT_UNAWARE_ERROR_TRACKER.trackError(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"loader": {
"name": "java_plain",
"version": "1.0"
},
"license": "MIT",
"global": {
"version": "1.0.0",
"contributors": [
{
"name": "Your Name",
"description": "The creator of this plugin"
}
]
},
"plugins": [
{
"id": "example",
"name": "Example Plugin",
"entrypoint": "com.example.ExamplePlugin"
}
]
}
18 changes: 14 additions & 4 deletions sponge/src/main/java/dev/faststats/sponge/SpongeMetricsImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.jspecify.annotations.Nullable;
import org.spongepowered.api.Platform;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.plugin.PluginContainer;

import java.nio.file.Path;
Expand All @@ -23,7 +22,8 @@ final class SpongeMetricsImpl extends SimpleMetrics implements SpongeMetrics {
# The server ID below is randomly generated and can be regenerated at any time.
#
# Enabling metrics has no noticeable performance impact.
# Enabling metrics is recommended, you can do so in the Sponge config.
# Enabling metrics is recommended, you can do so in the Sponge metrics.config,
# by setting the "global-state" property to "TRUE".
#
# If you suspect a plugin is collecting personal data or bypassing the Sponge config,
# please report it at: https://faststats.dev/abuse
Expand Down Expand Up @@ -51,6 +51,16 @@ private SpongeMetricsImpl(
startSubmitting();
}

@Override
protected String getOnboardingMessage() {
return """
This plugin uses FastStats to collect anonymous usage statistics.
No personal or identifying information is ever collected.
It is recommended to enable metrics by setting 'global-state=TRUE' in the sponge metrics config.
Learn more at: https://faststats.dev/info
""";
}

@Override
protected void appendDefaultData(JsonObject charts) {
charts.addProperty("online_mode", Sponge.server().isOnlineModeEnabled());
Expand Down Expand Up @@ -79,14 +89,14 @@ static class Factory extends SimpleMetrics.Factory<PluginContainer> {
protected final Logger logger;
protected final Path dataDirectory;

public Factory(Logger logger, @ConfigDir(sharedRoot = true) Path dataDirectory) {
public Factory(Logger logger, Path dataDirectory) {
this.logger = logger;
this.dataDirectory = dataDirectory;
}

@Override
public Metrics create(PluginContainer plugin) throws IllegalStateException, IllegalArgumentException {
var faststats = dataDirectory.resolveSibling("faststats");
var faststats = dataDirectory.resolve("faststats");
return new SpongeMetricsImpl(this, logger, plugin, faststats.resolve("config.properties"));
}
}
Expand Down
Loading