mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Implement real time statistic visualization (#16956)
Docs at https://trinitycore.atlassian.net/wiki/display/tc/Monitoring+a+TrinityCore+server * Common/Graphs: Initial proof of concept * Move influx db code to its own class * Reuse the same socket * Allow to log values of different categories * Allow to log events * Pass the timestamp to influxdb * Send events in batches * Send data async * Log server shutdown. Fix memory leak. * Allow to enable/disable Stats in the settings and at runtime * Read interval between each batch send from config * Add InfluxDB connection info to configs * Move each event category to its own table * Log pathfinding queries * Move categories table initialization to constructor using enum as key to avoid assigning the table name to the wrong enum value * Log player login/logout events. Pass the hostname correctly in the HTTP request. * Fix linux build * Handle "Connection: close" HTTP header, reconnecting on next scheduled send. Disable StatsLogger if connection fails, logging the error. * Add an enum for categories of logged values, it's still possible to pass a string instead of the enum. * Don't log the whole batchedData when InfluxDB returns an error, it's too long and unreadable on console. * Allow to call a function at a specified interval in thread-safe World::Update() context to log data like player count. * Log map tile load/unload * Core/StatsLogger: Allow logging more value types other than ints https://docs.influxdata.com/influxdb/v0.10/write_protocols/write_syntax/ * Fix a typo in string escape of StatsLogger * Yet more fixes to the escaping in FormatInfluxDBValue * DB/Gameobject: Fix respawn time of few Quest GameObjects By Tauriella, closes #16701 * DB/Misc: Fix some engrish By tkrokli closes #16648 * Tools/MMaps: Add format library linking to mmaps_generator (Very) partial cherry pick ofed75b0649a* Core/StatsLogger: Simplify code Convert values and categories arrays to maps initialized in-place Remove constructor and destructor * Core/StatsLogger: Add realm name to the event and value tags * Log amount of processed packet of each session * Apply recent singleton changes to sStatsLogger too * Fix influxdb data format if no realm name is present * Remove unneeded newlines from request body, fixes response 400 from InfluxDB 0.10 * Rename Reporting folder to Metric * Rename StatsLogger to Metric * Rename InfluxDB configs to Metric * Add Grafana dashboards * Add a random annoying macro * Move string formatting to Metric::SendBatch(), reducing performance footprint of Metric::LogEvent() and Metric::LogValue() * Update grafana graphs refresing tags on load and showing now-15m data, refreshing every minute. These settings can be modified in grafana. * Rename MetricData fields * Contrib/Grafana: Rename dashboard files * Contrib/Grafana: Replace hardcoded Windows/Ubuntu realm names by the default, Trinity * Config/Worldserver: Add missing section to the index * Contrib/Grafana: Add singlestat panels with current online players, update diff averages (1 min, 5 mins and 15 mins) http://i.imgur.com/Zi8lfvS.png * Core/Metric: Replace the enums MetricEventCategory and MetricValueCategory by strings For the sake of simplicity and less recompile time when adding new metrics, similar to how TC_LOG_* works * Contrib/Grafana: Display the current number of online players and not its average Closes #15075 (cherry picked from commit3ae1016082) # Conflicts: # src/server/game/Server/WorldSession.cpp # src/server/game/World/World.cpp # src/server/worldserver/Main.cpp
This commit is contained in:
889
contrib/grafana/1_General.json
Normal file
889
contrib/grafana/1_General.json
Normal file
@@ -0,0 +1,889 @@
|
||||
{
|
||||
"id": 1,
|
||||
"title": "General info",
|
||||
"originalTitle": "General info",
|
||||
"tags": [],
|
||||
"style": "dark",
|
||||
"timezone": "browser",
|
||||
"editable": true,
|
||||
"hideControls": false,
|
||||
"sharedCrosshair": false,
|
||||
"rows": [
|
||||
{
|
||||
"collapse": false,
|
||||
"editable": true,
|
||||
"height": "25px",
|
||||
"panels": [
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": false,
|
||||
"colors": [
|
||||
"rgba(245, 54, 54, 0.9)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(50, 172, 45, 0.97)"
|
||||
],
|
||||
"datasource": null,
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"format": "none",
|
||||
"id": 5,
|
||||
"interval": null,
|
||||
"isNew": true,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"span": 3,
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"auto"
|
||||
],
|
||||
"type": "time"
|
||||
}
|
||||
],
|
||||
"measurement": "online_players",
|
||||
"policy": "default",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"type": "field",
|
||||
"params": [
|
||||
"value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "last",
|
||||
"params": []
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/^$realm$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Online players",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "80%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "current",
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"hideTimeOverride": false
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": false,
|
||||
"colors": [
|
||||
"rgba(245, 54, 54, 0.9)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(50, 172, 45, 0.97)"
|
||||
],
|
||||
"datasource": null,
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"format": "none",
|
||||
"id": 6,
|
||||
"interval": null,
|
||||
"isNew": true,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"span": 3,
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"auto"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "update_time_diff",
|
||||
"policy": "default",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/^$realm$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Update diff (avg)",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "80%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "avg",
|
||||
"timeFrom": "1m"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": false,
|
||||
"colors": [
|
||||
"rgba(245, 54, 54, 0.9)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(50, 172, 45, 0.97)"
|
||||
],
|
||||
"datasource": null,
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"format": "none",
|
||||
"id": 7,
|
||||
"interval": null,
|
||||
"isNew": true,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"span": 3,
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"auto"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "update_time_diff",
|
||||
"policy": "default",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Update diff (avg)",
|
||||
"transparent": false,
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "80%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "avg",
|
||||
"timeFrom": "5m"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": false,
|
||||
"colors": [
|
||||
"rgba(245, 54, 54, 0.9)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(50, 172, 45, 0.97)"
|
||||
],
|
||||
"datasource": null,
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"format": "none",
|
||||
"id": 8,
|
||||
"interval": null,
|
||||
"isNew": true,
|
||||
"links": [],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"span": 3,
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"auto"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "update_time_diff",
|
||||
"policy": "default",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/^$realm$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Update diff (avg)",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "80%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "avg",
|
||||
"timeFrom": "15m",
|
||||
"timeShift": null
|
||||
}
|
||||
],
|
||||
"title": "New row"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"editable": true,
|
||||
"height": "250px",
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {
|
||||
"leftLogBase": 1,
|
||||
"leftMax": null,
|
||||
"leftMin": null,
|
||||
"rightLogBase": 1,
|
||||
"rightMax": null,
|
||||
"rightMin": null,
|
||||
"threshold1": null,
|
||||
"threshold1Color": "rgba(216, 200, 27, 0.27)",
|
||||
"threshold2": null,
|
||||
"threshold2Color": "rgba(234, 112, 112, 0.22)"
|
||||
},
|
||||
"id": 1,
|
||||
"isNew": true,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "Update diff",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "update_time_diff",
|
||||
"policy": "default",
|
||||
"query": "SELECT mean(\"value\") FROM \"update_time_diff\" WHERE \"realm\" =~ /$realm$/ AND $timeFilter GROUP BY time($interval) fill(null)",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/$realm$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Update diff",
|
||||
"tooltip": {
|
||||
"msResolution": false,
|
||||
"shared": true,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"x-axis": true,
|
||||
"xaxis": {
|
||||
"show": true
|
||||
},
|
||||
"y-axis": true,
|
||||
"y_formats": [
|
||||
"ms",
|
||||
"short"
|
||||
],
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "Row"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"editable": true,
|
||||
"height": "250px",
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {
|
||||
"leftLogBase": 1,
|
||||
"leftMax": null,
|
||||
"leftMin": null,
|
||||
"rightLogBase": 1,
|
||||
"rightMax": null,
|
||||
"rightMin": null,
|
||||
"threshold1": null,
|
||||
"threshold1Color": "rgba(216, 200, 27, 0.27)",
|
||||
"threshold2": null,
|
||||
"threshold2Color": "rgba(234, 112, 112, 0.22)"
|
||||
},
|
||||
"id": 4,
|
||||
"isNew": true,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "Online players",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "online_players",
|
||||
"policy": "default",
|
||||
"query": "SELECT mean(\"value\") FROM \"online_players\" WHERE \"realm\" =~ /$realm$/ AND $timeFilter GROUP BY time($interval) fill(null)",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/$realm$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Online players",
|
||||
"tooltip": {
|
||||
"msResolution": false,
|
||||
"shared": true,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"x-axis": true,
|
||||
"xaxis": {
|
||||
"show": true
|
||||
},
|
||||
"y-axis": true,
|
||||
"y_formats": [
|
||||
"short",
|
||||
"short"
|
||||
],
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "New row"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"editable": true,
|
||||
"height": "250px",
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {
|
||||
"leftLogBase": 1,
|
||||
"leftMax": null,
|
||||
"leftMin": null,
|
||||
"rightLogBase": 1,
|
||||
"rightMax": null,
|
||||
"rightMin": null,
|
||||
"threshold1": null,
|
||||
"threshold1Color": "rgba(216, 200, 27, 0.27)",
|
||||
"threshold2": null,
|
||||
"threshold2Color": "rgba(234, 112, 112, 0.22)"
|
||||
},
|
||||
"id": 3,
|
||||
"isNew": true,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [
|
||||
{
|
||||
"alias": "Logouts",
|
||||
"transform": "negative-Y"
|
||||
}
|
||||
],
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "Logins",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "player_events",
|
||||
"policy": "default",
|
||||
"query": "SELECT count(\"text\") FROM \"player_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'Login' AND $timeFilter GROUP BY time($interval) fill(0)",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"text"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "count"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=",
|
||||
"value": "Trinity"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alias": "Logouts",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"policy": "default",
|
||||
"query": "SELECT count(\"text\") FROM \"player_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'Logout' AND $timeFilter GROUP BY time($interval) fill(0)",
|
||||
"rawQuery": true,
|
||||
"refId": "B",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Player login/logout",
|
||||
"tooltip": {
|
||||
"msResolution": false,
|
||||
"shared": true,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"x-axis": true,
|
||||
"xaxis": {
|
||||
"show": true
|
||||
},
|
||||
"y-axis": true,
|
||||
"y_formats": [
|
||||
"short",
|
||||
"short"
|
||||
],
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "New row"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"from": "now-15m",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"now": true,
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allFormat": "regex values",
|
||||
"current": {
|
||||
"text": "Trinity",
|
||||
"value": "Trinity"
|
||||
},
|
||||
"datasource": null,
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"multiFormat": "regex values",
|
||||
"name": "realm",
|
||||
"options": [
|
||||
{
|
||||
"text": "Trinity",
|
||||
"value": "Trinity",
|
||||
"selected": true
|
||||
}
|
||||
],
|
||||
"query": "show tag values from events with key = realm",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"type": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"datasource": "Influx",
|
||||
"enable": true,
|
||||
"iconColor": "#C0C6BE",
|
||||
"iconSize": 13,
|
||||
"lineColor": "rgba(255, 96, 96, 0.592157)",
|
||||
"name": "Global Events",
|
||||
"query": "select title, text from events where $timeFilter and realm =~ /$realm$/",
|
||||
"showLine": true,
|
||||
"textColumn": "text",
|
||||
"titleColumn": "title"
|
||||
}
|
||||
]
|
||||
},
|
||||
"refresh": "1m",
|
||||
"schemaVersion": 12,
|
||||
"version": 7,
|
||||
"links": []
|
||||
}
|
||||
339
contrib/grafana/2_Maps.json
Normal file
339
contrib/grafana/2_Maps.json
Normal file
@@ -0,0 +1,339 @@
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Maps, vmaps and mmaps",
|
||||
"originalTitle": "Maps, vmaps and mmaps",
|
||||
"tags": [],
|
||||
"style": "dark",
|
||||
"timezone": "browser",
|
||||
"editable": true,
|
||||
"hideControls": false,
|
||||
"sharedCrosshair": false,
|
||||
"rows": [
|
||||
{
|
||||
"collapse": false,
|
||||
"editable": true,
|
||||
"height": "250px",
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {
|
||||
"leftLogBase": 1,
|
||||
"leftMax": null,
|
||||
"leftMin": null,
|
||||
"rightLogBase": 1,
|
||||
"rightMax": null,
|
||||
"rightMin": null,
|
||||
"threshold1": null,
|
||||
"threshold1Color": "rgba(216, 200, 27, 0.27)",
|
||||
"threshold2": null,
|
||||
"threshold2Color": "rgba(234, 112, 112, 0.22)"
|
||||
},
|
||||
"id": 2,
|
||||
"isNew": true,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [
|
||||
{
|
||||
"alias": "Unload tile",
|
||||
"transform": "negative-Y"
|
||||
}
|
||||
],
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "Load tile",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"0"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"query": "SELECT count(\"title\") FROM \"map_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'LoadMapTile' AND $timeFilter GROUP BY time($interval) fill(0)",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"alias": "Unload tile",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"query": "SELECT count(\"title\") FROM \"map_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'UnloadMapTile' AND $timeFilter GROUP BY time($interval) fill(0)",
|
||||
"rawQuery": true,
|
||||
"refId": "B",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Map",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"x-axis": true,
|
||||
"y-axis": true,
|
||||
"y_formats": [
|
||||
"short",
|
||||
"short"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "Row"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"editable": true,
|
||||
"height": "250px",
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {
|
||||
"leftLogBase": 1,
|
||||
"leftMax": null,
|
||||
"leftMin": null,
|
||||
"rightLogBase": 1,
|
||||
"rightMax": null,
|
||||
"rightMin": null,
|
||||
"threshold1": null,
|
||||
"threshold1Color": "rgba(216, 200, 27, 0.27)",
|
||||
"threshold2": null,
|
||||
"threshold2Color": "rgba(234, 112, 112, 0.22)"
|
||||
},
|
||||
"id": 1,
|
||||
"isNew": true,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "Pathfinding queries",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"null"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"query": "SELECT count(\"title\") FROM \"mmap_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'CalculatePath' AND $timeFilter GROUP BY time($interval) fill(0)",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "MMap",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"x-axis": true,
|
||||
"y-axis": true,
|
||||
"y_formats": [
|
||||
"short",
|
||||
"short"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "New row"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"from": "now-15m",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"now": true,
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allFormat": "regex values",
|
||||
"current": {
|
||||
"text": "Trinity",
|
||||
"value": "Trinity"
|
||||
},
|
||||
"datasource": "Influx",
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"multiFormat": "regex values",
|
||||
"name": "realm",
|
||||
"options": [
|
||||
{
|
||||
"text": "Trinity",
|
||||
"value": "Trinity",
|
||||
"selected": true
|
||||
}
|
||||
],
|
||||
"query": "show tag values from events with key = realm",
|
||||
"refresh": true,
|
||||
"type": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"datasource": "Influx",
|
||||
"enable": true,
|
||||
"iconColor": "#C0C6BE",
|
||||
"iconSize": 13,
|
||||
"lineColor": "rgba(255, 96, 96, 0.592157)",
|
||||
"name": "Global Events",
|
||||
"query": "select title, text from events where $timeFilter and realm =~ /$realm$/",
|
||||
"showLine": true,
|
||||
"textColumn": "text",
|
||||
"titleColumn": "title"
|
||||
}
|
||||
]
|
||||
},
|
||||
"refresh": "1m",
|
||||
"schemaVersion": 8,
|
||||
"version": 11,
|
||||
"links": []
|
||||
}
|
||||
242
contrib/grafana/3_Network.json
Normal file
242
contrib/grafana/3_Network.json
Normal file
@@ -0,0 +1,242 @@
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Network",
|
||||
"originalTitle": "Network",
|
||||
"tags": [],
|
||||
"style": "dark",
|
||||
"timezone": "browser",
|
||||
"editable": true,
|
||||
"hideControls": false,
|
||||
"sharedCrosshair": false,
|
||||
"rows": [
|
||||
{
|
||||
"collapse": false,
|
||||
"editable": true,
|
||||
"height": "250px",
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {
|
||||
"leftLogBase": 1,
|
||||
"leftMax": null,
|
||||
"leftMin": null,
|
||||
"rightLogBase": 1,
|
||||
"rightMax": null,
|
||||
"rightMin": null,
|
||||
"threshold1": null,
|
||||
"threshold1Color": "rgba(216, 200, 27, 0.27)",
|
||||
"threshold2": null,
|
||||
"threshold2Color": "rgba(234, 112, 112, 0.22)"
|
||||
},
|
||||
"id": 1,
|
||||
"isNew": true,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "Processed packets",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"0"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "processed_packets",
|
||||
"query": "SELECT sum(\"value\") FROM \"processed_packets\" WHERE \"realm\" =~ /$realm$/ AND $timeFilter GROUP BY time($interval) fill(0)",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "sum"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/$realm$/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alias": "Processed packets / mean per session",
|
||||
"dsType": "influxdb",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"0"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "processed_packets",
|
||||
"query": "SELECT mean(\"value\") FROM \"processed_packets\" WHERE \"realm\" =~ /$realm$/ AND $timeFilter GROUP BY time($interval) fill(0)",
|
||||
"refId": "B",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/$realm$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Processed packets",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"x-axis": true,
|
||||
"y-axis": true,
|
||||
"y_formats": [
|
||||
"short",
|
||||
"short"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "Row"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"from": "now-15m",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"now": true,
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allFormat": "regex values",
|
||||
"current": {
|
||||
"text": "Trinity",
|
||||
"value": "Trinity"
|
||||
},
|
||||
"datasource": "Influx",
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"multiFormat": "regex values",
|
||||
"name": "realm",
|
||||
"options": [
|
||||
{
|
||||
"text": "Trinity",
|
||||
"value": "Trinity",
|
||||
"selected": true
|
||||
}
|
||||
],
|
||||
"query": "show tag values from events with key = realm",
|
||||
"refresh": true,
|
||||
"type": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"datasource": "Influx",
|
||||
"enable": true,
|
||||
"iconColor": "#C0C6BE",
|
||||
"iconSize": 13,
|
||||
"lineColor": "rgba(255, 96, 96, 0.592157)",
|
||||
"name": "Global Events",
|
||||
"query": "select title, text from events where $timeFilter and realm =~ /$realm$/",
|
||||
"showLine": true,
|
||||
"textColumn": "text",
|
||||
"titleColumn": "title"
|
||||
}
|
||||
]
|
||||
},
|
||||
"refresh": "1m",
|
||||
"schemaVersion": 8,
|
||||
"version": 7,
|
||||
"links": []
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "VMapDefinitions.h"
|
||||
#include "Log.h"
|
||||
#include "Errors.h"
|
||||
#include "Metric.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@@ -415,6 +416,8 @@ namespace VMAP
|
||||
}
|
||||
else
|
||||
iLoadedTiles[packTileID(tileX, tileY)] = false;
|
||||
TC_METRIC_EVENT("map_events", "LoadMapTile",
|
||||
"Map: " + std::to_string(iMapID) + " TileX: " + std::to_string(tileX) + " TileY: " + std::to_string(tileY));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -473,6 +476,8 @@ namespace VMAP
|
||||
}
|
||||
}
|
||||
iLoadedTiles.erase(tile);
|
||||
TC_METRIC_EVENT("map_events", "UnloadMapTile",
|
||||
"Map: " + std::to_string(iMapID) + " TileX: " + std::to_string(tileX) + " TileY: " + std::to_string(tileY));
|
||||
}
|
||||
|
||||
void StaticMapTree::getModelInstances(ModelInstance* &models, uint32 &count)
|
||||
|
||||
235
src/common/Metric/Metric.cpp
Normal file
235
src/common/Metric/Metric.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Metric.h"
|
||||
#include "Log.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
|
||||
void Metric::Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger)
|
||||
{
|
||||
_realmName = realmName;
|
||||
_batchTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService);
|
||||
_overallStatusTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService);
|
||||
_overallStatusLogger = overallStatusLogger;
|
||||
LoadFromConfigs();
|
||||
}
|
||||
|
||||
bool Metric::Connect()
|
||||
{
|
||||
_dataStream.connect(_hostname, _port);
|
||||
auto error = _dataStream.error();
|
||||
if (error)
|
||||
{
|
||||
TC_LOG_ERROR("metric", "Error connecting to '%s:%s', disabling Metric. Error message : %s",
|
||||
_hostname.c_str(), _port.c_str(), error.message().c_str());
|
||||
_enabled = false;
|
||||
return false;
|
||||
}
|
||||
_dataStream.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Metric::LoadFromConfigs()
|
||||
{
|
||||
bool previousValue = _enabled;
|
||||
_enabled = sConfigMgr->GetBoolDefault("Metric.Enable", false);
|
||||
_updateInterval = sConfigMgr->GetIntDefault("Metric.Interval", 10);
|
||||
if (_updateInterval < 1)
|
||||
{
|
||||
TC_LOG_ERROR("metric", "'Metric.Interval' config set to %d, overriding to 1.", _updateInterval);
|
||||
_updateInterval = 1;
|
||||
}
|
||||
|
||||
_overallStatusTimerInterval = sConfigMgr->GetIntDefault("Metric.OverallStatusInterval", 1);
|
||||
if (_overallStatusTimerInterval < 1)
|
||||
{
|
||||
TC_LOG_ERROR("metric", "'Metric.OverallStatusInterval' config set to %d, overriding to 1.", _overallStatusTimerInterval);
|
||||
_overallStatusTimerInterval = 1;
|
||||
}
|
||||
|
||||
// Schedule a send at this point only if the config changed from Disabled to Enabled.
|
||||
// Cancel any scheduled operation if the config changed from Enabled to Disabled.
|
||||
if (_enabled && !previousValue)
|
||||
{
|
||||
std::string connectionInfo = sConfigMgr->GetStringDefault("Metric.ConnectionInfo", "");
|
||||
if (connectionInfo.empty())
|
||||
{
|
||||
TC_LOG_ERROR("metric", "'Metric.ConnectionInfo' not specified in configuration file.");
|
||||
return;
|
||||
}
|
||||
|
||||
Tokenizer tokens(connectionInfo, ';');
|
||||
if (tokens.size() != 3)
|
||||
{
|
||||
TC_LOG_ERROR("metric", "'Metric.ConnectionInfo' specified with wrong format in configuration file.");
|
||||
return;
|
||||
}
|
||||
|
||||
_hostname.assign(tokens[0]);
|
||||
_port.assign(tokens[1]);
|
||||
_databaseName.assign(tokens[2]);
|
||||
Connect();
|
||||
|
||||
ScheduleSend();
|
||||
ScheduleOverallStatusLog();
|
||||
}
|
||||
}
|
||||
|
||||
void Metric::Update()
|
||||
{
|
||||
if (_overallStatusTimerTriggered)
|
||||
{
|
||||
_overallStatusTimerTriggered = false;
|
||||
_overallStatusLogger();
|
||||
}
|
||||
}
|
||||
|
||||
void Metric::LogEvent(std::string const& category, std::string const& title, std::string const& description)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
||||
MetricData* data = new MetricData;
|
||||
data->Category = category;
|
||||
data->Timestamp = system_clock::now();
|
||||
data->Type = METRIC_DATA_EVENT;
|
||||
data->Title = title;
|
||||
data->Text = description;
|
||||
|
||||
_queuedData.Enqueue(data);
|
||||
}
|
||||
|
||||
void Metric::SendBatch()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
||||
std::stringstream batchedData;
|
||||
MetricData* data;
|
||||
bool firstLoop = true;
|
||||
while (_queuedData.Dequeue(data))
|
||||
{
|
||||
if (!firstLoop)
|
||||
batchedData << "\n";
|
||||
|
||||
batchedData << data->Category;
|
||||
if (!_realmName.empty())
|
||||
batchedData << ",realm=" << _realmName;
|
||||
|
||||
batchedData << " ";
|
||||
|
||||
switch (data->Type)
|
||||
{
|
||||
case METRIC_DATA_VALUE:
|
||||
batchedData << "value=" << data->Value;
|
||||
break;
|
||||
case METRIC_DATA_EVENT:
|
||||
batchedData << "title=\"" << data->Title << "\",text=\"" << data->Text << "\"";
|
||||
break;
|
||||
}
|
||||
|
||||
batchedData << " ";
|
||||
|
||||
batchedData << std::to_string(duration_cast<nanoseconds>(data->Timestamp.time_since_epoch()).count());
|
||||
|
||||
firstLoop = false;
|
||||
delete data;
|
||||
}
|
||||
|
||||
// Check if there's any data to send
|
||||
if (batchedData.tellp() == std::streampos(0))
|
||||
{
|
||||
ScheduleSend();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_dataStream.good() && !Connect())
|
||||
return;
|
||||
|
||||
_dataStream << "POST " << "/write?db=" << _databaseName << " HTTP/1.1\r\n";
|
||||
_dataStream << "Host: " << _hostname << ":" << _port << "\r\n";
|
||||
_dataStream << "Accept: */*\r\n";
|
||||
_dataStream << "Content-Type: application/octet-stream\r\n";
|
||||
_dataStream << "Content-Transfer-Encoding: binary\r\n";
|
||||
|
||||
_dataStream << "Content-Length: " << std::to_string(batchedData.tellp()) << "\r\n\r\n";
|
||||
_dataStream << batchedData.rdbuf();
|
||||
|
||||
std::string http_version;
|
||||
_dataStream >> http_version;
|
||||
unsigned int status_code = 0;
|
||||
_dataStream >> status_code;
|
||||
if (status_code != 204)
|
||||
{
|
||||
TC_LOG_ERROR("metric", "Error sending data, returned HTTP code: %u", status_code);
|
||||
}
|
||||
|
||||
// Read and ignore the status description
|
||||
std::string status_description;
|
||||
std::getline(_dataStream, status_description);
|
||||
// Read headers
|
||||
std::string header;
|
||||
while (std::getline(_dataStream, header) && header != "\r")
|
||||
{
|
||||
if (header == "Connection: close\r")
|
||||
_dataStream.close();
|
||||
}
|
||||
|
||||
ScheduleSend();
|
||||
}
|
||||
|
||||
void Metric::ScheduleSend()
|
||||
{
|
||||
if (_enabled)
|
||||
{
|
||||
_batchTimer->expires_from_now(boost::posix_time::seconds(_updateInterval));
|
||||
_batchTimer->async_wait(std::bind(&Metric::SendBatch, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
_dataStream.close();
|
||||
MetricData* data;
|
||||
// Clear the queue
|
||||
while (_queuedData.Dequeue(data))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void Metric::ForceSend()
|
||||
{
|
||||
// Send what's queued only if io_service is stopped (so only on shutdown)
|
||||
if (_enabled && _batchTimer->get_io_service().stopped())
|
||||
SendBatch();
|
||||
}
|
||||
|
||||
void Metric::ScheduleOverallStatusLog()
|
||||
{
|
||||
if (_enabled)
|
||||
{
|
||||
_overallStatusTimer->expires_from_now(boost::posix_time::seconds(_overallStatusTimerInterval));
|
||||
_overallStatusTimer->async_wait([this](const boost::system::error_code&)
|
||||
{
|
||||
_overallStatusTimerTriggered = true;
|
||||
ScheduleOverallStatusLog();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Metric* Metric::instance()
|
||||
{
|
||||
static Metric instance;
|
||||
return &instance;
|
||||
}
|
||||
141
src/common/Metric/Metric.h
Normal file
141
src/common/Metric/Metric.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef METRIC_H__
|
||||
#define METRIC_H__
|
||||
|
||||
#include "Common.h"
|
||||
#include "Threading/MPSCQueue.h"
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
enum MetricDataType
|
||||
{
|
||||
METRIC_DATA_VALUE,
|
||||
METRIC_DATA_EVENT
|
||||
};
|
||||
|
||||
struct MetricData
|
||||
{
|
||||
std::string Category;
|
||||
std::chrono::time_point<std::chrono::system_clock> Timestamp;
|
||||
MetricDataType Type;
|
||||
|
||||
// LogValue-specific fields
|
||||
std::string Value;
|
||||
|
||||
// LogEvent-specific fields
|
||||
std::string Title;
|
||||
std::string Text;
|
||||
};
|
||||
|
||||
class TC_COMMON_API Metric
|
||||
{
|
||||
private:
|
||||
boost::asio::ip::tcp::iostream _dataStream;
|
||||
MPSCQueue<MetricData> _queuedData;
|
||||
std::unique_ptr<boost::asio::deadline_timer> _batchTimer;
|
||||
std::unique_ptr<boost::asio::deadline_timer> _overallStatusTimer;
|
||||
int32 _updateInterval = 0;
|
||||
int32 _overallStatusTimerInterval = 0;
|
||||
bool _enabled = false;
|
||||
bool _overallStatusTimerTriggered = false;
|
||||
std::string _hostname;
|
||||
std::string _port;
|
||||
std::string _databaseName;
|
||||
std::function<void()> _overallStatusLogger;
|
||||
std::string _realmName;
|
||||
|
||||
bool Connect();
|
||||
void SendBatch();
|
||||
void ScheduleSend();
|
||||
void ScheduleOverallStatusLog();
|
||||
|
||||
template<class T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||
static std::string FormatInfluxDBValue(T value) { return std::to_string(value) + 'i'; }
|
||||
|
||||
static std::string FormatInfluxDBValue(std::string const& value)
|
||||
{
|
||||
return '"' + boost::replace_all_copy(value, "\"", "\\\"") + '"';
|
||||
}
|
||||
|
||||
static std::string FormatInfluxDBValue(bool value) { return value ? "t" : "f"; }
|
||||
static std::string FormatInfluxDBValue(const char* value) { return FormatInfluxDBValue(std::string(value)); }
|
||||
static std::string FormatInfluxDBValue(double value) { return std::to_string(value); }
|
||||
static std::string FormatInfluxDBValue(float value) { return FormatInfluxDBValue(double(value)); }
|
||||
|
||||
public:
|
||||
static Metric* instance();
|
||||
|
||||
void Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger = [](){});
|
||||
void LoadFromConfigs();
|
||||
void Update();
|
||||
|
||||
template<class T>
|
||||
void LogValue(std::string const& category, T value)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
||||
MetricData* data = new MetricData;
|
||||
data->Category = category;
|
||||
data->Timestamp = system_clock::now();
|
||||
data->Type = METRIC_DATA_VALUE;
|
||||
data->Value = FormatInfluxDBValue(value);
|
||||
|
||||
_queuedData.Enqueue(data);
|
||||
}
|
||||
|
||||
void LogEvent(std::string const& category, std::string const& title, std::string const& description);
|
||||
|
||||
void ForceSend();
|
||||
bool IsEnabled() const { return _enabled; }
|
||||
};
|
||||
|
||||
#define sMetric Metric::instance()
|
||||
|
||||
#if PLATFORM != PLATFORM_WINDOWS
|
||||
#define TC_METRIC_EVENT(category, title, description) \
|
||||
do { \
|
||||
if (sMetric->IsEnabled()) \
|
||||
sMetric->LogEvent(category, title, description); \
|
||||
} while (0)
|
||||
#define TC_METRIC_VALUE(category, value) \
|
||||
do { \
|
||||
if (sMetric->IsEnabled()) \
|
||||
sMetric->LogValue(category, value); \
|
||||
} while (0)
|
||||
#else
|
||||
#define TC_METRIC_EVENT(category, title, description) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:4127)) \
|
||||
do { \
|
||||
if (sMetric->IsEnabled()) \
|
||||
sMetric->LogEvent(category, title, description); \
|
||||
} while (0) \
|
||||
__pragma(warning(pop))
|
||||
#define TC_METRIC_VALUE(category, value) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:4127)) \
|
||||
do { \
|
||||
if (sMetric->IsEnabled()) \
|
||||
sMetric->LogValue(category, value); \
|
||||
} while (0) \
|
||||
__pragma(warning(pop))
|
||||
#endif
|
||||
|
||||
#endif // METRIC_H__
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "Metric.h"
|
||||
|
||||
class LoginQueryHolder : public SQLQueryHolder
|
||||
{
|
||||
@@ -1147,6 +1148,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
|
||||
|
||||
sScriptMgr->OnPlayerLogin(pCurrChar, firstLogin);
|
||||
|
||||
TC_METRIC_EVENT("player_events", "Login", pCurrChar->GetName());
|
||||
|
||||
delete holder;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "DisableMgr.h"
|
||||
#include "DetourCommon.h"
|
||||
#include "DetourNavMeshQuery.h"
|
||||
#include "Metric.h"
|
||||
|
||||
////////////////// PathGenerator //////////////////
|
||||
PathGenerator::PathGenerator(const Unit* owner) :
|
||||
@@ -62,6 +63,8 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
|
||||
if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z))
|
||||
return false;
|
||||
|
||||
TC_METRIC_EVENT("mmap_events", "CalculatePath", "");
|
||||
|
||||
G3D::Vector3 dest(destX, destY, destZ);
|
||||
SetEndPosition(dest);
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "BattlePetMgr.h"
|
||||
#include "PacketUtilities.h"
|
||||
#include "CollectionMgr.h"
|
||||
#include "Metric.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
@@ -456,6 +457,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
break;
|
||||
}
|
||||
|
||||
TC_METRIC_VALUE("processed_packets", processedPackets);
|
||||
|
||||
_recvQueue.readd(requeuePackets.begin(), requeuePackets.end());
|
||||
|
||||
if (m_Socket[CONNECTION_TYPE_REALM] && m_Socket[CONNECTION_TYPE_REALM]->IsOpen() && _warden)
|
||||
@@ -614,6 +617,8 @@ void WorldSession::LogoutPlayer(bool save)
|
||||
//! Call script hook before deletion
|
||||
sScriptMgr->OnPlayerLogout(_player);
|
||||
|
||||
TC_METRIC_EVENT("player_events", "Logout", _player->GetName());
|
||||
|
||||
//! Remove the player from the world
|
||||
// the player may not be in the world when logging out
|
||||
// e.g if he got disconnected during a transfer to another map
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#include "SkillDiscovery.h"
|
||||
#include "SkillExtraItems.h"
|
||||
#include "SmartAI.h"
|
||||
#include "Metric.h"
|
||||
#include "SupportMgr.h"
|
||||
#include "TaxiPathGraph.h"
|
||||
#include "TransportMgr.h"
|
||||
@@ -437,6 +438,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
return;
|
||||
}
|
||||
sLog->LoadFromConfig();
|
||||
sMetric->LoadFromConfigs();
|
||||
}
|
||||
|
||||
m_defaultDbcLocale = LocaleConstant(sConfigMgr->GetIntDefault("DBC.Locale", 0));
|
||||
@@ -2128,6 +2130,8 @@ void World::SetInitialWorldSettings()
|
||||
|
||||
TC_LOG_INFO("server.worldserver", "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
|
||||
|
||||
TC_METRIC_EVENT("events", "World initialized", "World initialized in " + std::to_string(startupDuration / 60000) + " minutes " + std::to_string((startupDuration % 60000) / 1000) + " seconds");
|
||||
|
||||
if (uint32 realmId = sConfigMgr->GetIntDefault("RealmID", 0)) // 0 reserved for auth
|
||||
sLog->SetRealmId(realmId);
|
||||
}
|
||||
@@ -2430,6 +2434,10 @@ void World::Update(uint32 diff)
|
||||
ProcessCliCommands();
|
||||
|
||||
sScriptMgr->OnWorldUpdate(diff);
|
||||
|
||||
// Stats logger update
|
||||
sMetric->Update();
|
||||
TC_METRIC_VALUE("update_time_diff", diff);
|
||||
}
|
||||
|
||||
void World::ForceGameEventUpdate()
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "RealmList.h"
|
||||
#include "DatabaseLoader.h"
|
||||
#include "AppenderDB.h"
|
||||
#include "Metric.h"
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
@@ -200,6 +201,13 @@ extern int main(int argc, char** argv)
|
||||
|
||||
LoadRealmInfo();
|
||||
|
||||
sMetric->Initialize(realm.Name, _ioService, []()
|
||||
{
|
||||
TC_METRIC_VALUE("online_players", sWorld->GetPlayerCount());
|
||||
});
|
||||
|
||||
TC_METRIC_EVENT("events", "Worldserver started", "");
|
||||
|
||||
// Initialize the World
|
||||
sScriptMgr->SetScriptLoader(AddScripts);
|
||||
sWorld->SetInitialWorldSettings();
|
||||
@@ -300,6 +308,9 @@ extern int main(int argc, char** argv)
|
||||
|
||||
StopDB();
|
||||
|
||||
TC_METRIC_EVENT("events", "Worldserver shutdown", "");
|
||||
sMetric->ForceSend();
|
||||
|
||||
TC_LOG_INFO("server.worldserver", "Halting process...");
|
||||
|
||||
ShutdownCLIThread(cliThread);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
# LOGGING SYSTEM SETTINGS
|
||||
# CURRENCIES SETTINGS
|
||||
# PACKET SPOOF PROTECTION SETTINGS
|
||||
# METRIC SETTINGS
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
@@ -3853,3 +3854,41 @@ PacketSpoof.BanDuration = 86400
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# METRIC SETTINGS
|
||||
#
|
||||
# These settings control the statistics sent to the metric database (currently InfluxDB)
|
||||
#
|
||||
# Metric.Enable
|
||||
# Description: Enables statistics sent to the metric database.
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
Metric.Enable = 0
|
||||
|
||||
#
|
||||
# Metric.Interval
|
||||
# Description: Interval between every batch of data sent in seconds
|
||||
# Default: 10 seconds
|
||||
#
|
||||
|
||||
Metric.Interval = 10
|
||||
|
||||
#
|
||||
# Metric.ConnectionInfo
|
||||
# Description: Connection settings for metric database (currently InfluxDB).
|
||||
# Example: "hostname;port;database"
|
||||
# Default: "127.0.0.1;8086;worldserver"
|
||||
|
||||
Metric.ConnectionInfo = "127.0.0.1;8086;worldserver"
|
||||
|
||||
#
|
||||
# Metric.OverallStatusInterval
|
||||
# Description: Interval between every gathering of overall worldserver status data in seconds
|
||||
# Default: 1 second
|
||||
#
|
||||
|
||||
Metric.OverallStatusInterval = 1
|
||||
|
||||
###################################################################################################
|
||||
|
||||
Reference in New Issue
Block a user