feat: implemented pushing player event metrics

This commit is contained in:
Andrey Terentev 2024-11-29 13:46:45 +07:00
parent 6cd1edd49a
commit 285e050168
7 changed files with 122 additions and 0 deletions

View File

@ -11,4 +11,8 @@ dependencies {
api 'team.unnamed:creative-api:1.7.3' api 'team.unnamed:creative-api:1.7.3'
api 'team.unnamed:creative-serializer-minecraft:1.7.3' api 'team.unnamed:creative-serializer-minecraft:1.7.3'
api 'team.unnamed:creative-server:1.7.3' api 'team.unnamed:creative-server:1.7.3'
api 'org.sql2o:sql2o:1.8.0'
api 'com.clickhouse:clickhouse-jdbc:0.7.1'
api 'org.lz4:lz4-java:1.8.0'
} }

View File

@ -0,0 +1,50 @@
package ru.dragonestia.msb3.api.metrics;
import com.google.gson.Gson;
import lombok.extern.log4j.Log4j2;
import net.minestom.server.entity.Player;
import org.jetbrains.annotations.Nullable;
import ru.dragonestia.msb3.api.module.ClickhouseMetricsModule;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
@Log4j2
public class PlayerEventMetrics {
private static final int MAX_ALERTS = 5;
private static final AtomicInteger alertAboutModuleDisabled = new AtomicInteger(0);
private static final Gson GSON = new Gson();
private PlayerEventMetrics() {}
public static void push(Player player, String eventName, @Nullable Object details) {
var sql2o = ClickhouseMetricsModule.getSql2o();
if (sql2o == null) {
var alerts = alertAboutModuleDisabled.incrementAndGet();
if (alerts > MAX_ALERTS) return;
log.warn("ClickhouseMetricsModule is not initialized. Skipping sending metrics [{}/{}]", alerts, MAX_ALERTS);
if (alerts == MAX_ALERTS) {
log.warn("Disabling logs with warnings about ClickhouseMetricsModule");
}
return;
}
CompletableFuture.runAsync(() -> {
log.debug("Sending event '{}' for player '{}'({}) with data '{}'", eventName, player.getUsername(), player.getUuid(), GSON.toJson(details));
try (var con = sql2o.open()) {
con.createQuery("insert into events (uuid, player_name, timestamp, event_type, details) values (:uuid, :player_name, now(), :event_type, :details)", false)
.addParameter("uuid", player.getUuid())
.addParameter("player_name", player.getUsername())
.addParameter("event_type", eventName)
.addParameter("details", GSON.toJson(details))
.executeUpdate();
} catch (Exception ex) {
log.error(ex, ex);
}
});
}
}

View File

@ -0,0 +1,21 @@
package ru.dragonestia.msb3.api.module;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.sql2o.Sql2o;
@Log4j2
public class ClickhouseMetricsModule {
@Getter private static Sql2o sql2o;
private ClickhouseMetricsModule() {}
public static synchronized void init(String url, String username, String password) {
if (sql2o != null) return;
sql2o = new Sql2o(url, username, password);
log.info("Enabled Clickhouse metrics module");
}
}

7
clickhouse/config.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<yandex>
<profiles>
<default>
</default>
</profiles>
</yandex>

View File

@ -0,0 +1,11 @@
version: '3'
services:
clickhouse:
image: yandex/clickhouse-server
ports:
- '8123:8123'
volumes:
- './users.xml:/etc/clickhouse-server/users.d/users.xml'
- './init.sql:/docker-entrypoint-initdb.d/crate_database.sql'
- './config.xml:/etc/clickhouse-server/users.d/config.xml'

11
clickhouse/init.sql Normal file
View File

@ -0,0 +1,11 @@
create database if not exists msb3;
create table if not exists msb3.events
(
uuid UUID,
player_name String(32),
timestamp DateTime default now(),
event_type LowCardinality(String),
details Nullable(String)
) engine = ReplacingMergeTree partition by toYYYYMM(timestamp)
primary key (uuid, event_type, timestamp);

18
clickhouse/users.xml Normal file
View File

@ -0,0 +1,18 @@
<yandex>
<users>
<default>
<networks replace="replace">
<ip>::/1</ip>
<ip>127.0.0.1</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</default>
<msb3>
<password>example</password>
<profile>default</profile>
<quota>default</quota>
<default_database>msb3</default_database>
</msb3>
</users>
</yandex>