feat(Core/Metrics): implement real time statistic visualization (#8663)
This commit is contained in:
parent
7c363c9040
commit
a650fd495c
1319
apps/grafana/1_General.json
Normal file
1319
apps/grafana/1_General.json
Normal file
File diff suppressed because it is too large
Load Diff
691
apps/grafana/2_Maps.json
Normal file
691
apps/grafana/2_Maps.json
Normal file
@ -0,0 +1,691 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": 6,
|
||||
"iteration": 1595939001794,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"grid": {},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"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",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [
|
||||
{
|
||||
"alias": "Unload tile",
|
||||
"transform": "negative-Y"
|
||||
}
|
||||
],
|
||||
"spaceLength": 10,
|
||||
"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": []
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Map",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"grid": {},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 7
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"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",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"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": []
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "MMap",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 5,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 14
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 4,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"hideEmpty": false,
|
||||
"hideZero": true,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "Map $tag_map_id Instance $tag_map_instanceid",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$__interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"map_id"
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"map_instanceid"
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"none"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "map_creatures",
|
||||
"orderByTime": "ASC",
|
||||
"policy": "default",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/^$realm$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Creatures",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"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
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 5,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 22
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 5,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"hideEmpty": false,
|
||||
"hideZero": true,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "Map $tag_map_id Instance $tag_map_instanceid",
|
||||
"groupBy": [
|
||||
{
|
||||
"params": [
|
||||
"$__interval"
|
||||
],
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"map_id"
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"map_instanceid"
|
||||
],
|
||||
"type": "tag"
|
||||
},
|
||||
{
|
||||
"params": [
|
||||
"none"
|
||||
],
|
||||
"type": "fill"
|
||||
}
|
||||
],
|
||||
"measurement": "map_gameobjects",
|
||||
"orderByTime": "ASC",
|
||||
"policy": "default",
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
"select": [
|
||||
[
|
||||
{
|
||||
"params": [
|
||||
"value"
|
||||
],
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"params": [],
|
||||
"type": "mean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "realm",
|
||||
"operator": "=~",
|
||||
"value": "/^$realm$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Gameobjects",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"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
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": "1m",
|
||||
"schemaVersion": 25,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allFormat": "regex values",
|
||||
"allValue": null,
|
||||
"current": {
|
||||
"text": "Acore",
|
||||
"value": "Acore"
|
||||
},
|
||||
"datasource": "Influx",
|
||||
"definition": "",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": null,
|
||||
"multi": false,
|
||||
"multiFormat": "regex values",
|
||||
"name": "realm",
|
||||
"options": [],
|
||||
"query": "show tag values from events with key = realm",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-15m",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"now": true,
|
||||
"refresh_intervals": [
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "Maps, vmaps and mmaps",
|
||||
"uid": "6IhqWiWGz",
|
||||
"version": 2
|
||||
}
|
||||
280
apps/grafana/3_Network.json
Normal file
280
apps/grafana/3_Network.json
Normal file
@ -0,0 +1,280 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": 7,
|
||||
"iteration": 1595939048589,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "Influx",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"grid": {},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"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",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"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$/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Processed packets",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": "1m",
|
||||
"schemaVersion": 25,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allFormat": "regex values",
|
||||
"allValue": null,
|
||||
"current": {
|
||||
"text": "Acore",
|
||||
"value": "Acore"
|
||||
},
|
||||
"datasource": "Influx",
|
||||
"definition": "",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": null,
|
||||
"multi": false,
|
||||
"multiFormat": "regex values",
|
||||
"name": "realm",
|
||||
"options": [],
|
||||
"query": "show tag values from events with key = realm",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-15m",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"now": true,
|
||||
"refresh_intervals": [
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "Network",
|
||||
"uid": "_QtkMmWMk",
|
||||
"version": 2
|
||||
}
|
||||
1677
apps/grafana/4_Performance_profiling.json
Normal file
1677
apps/grafana/4_Performance_profiling.json
Normal file
File diff suppressed because it is too large
Load Diff
2
conf/dist/config.cmake
vendored
2
conf/dist/config.cmake
vendored
@ -67,6 +67,8 @@ option(WITHOUT_GIT "Disable the GIT testing routines"
|
||||
option(ENABLE_VMAP_CHECKS "Enable Checks relative to DisableMgr system on vmap" 1)
|
||||
option(WITH_DYNAMIC_LINKING "Enable dynamic library linking." 0)
|
||||
option(WITH_STRICT_DATABASE_TYPE_CHECKS "Enable strict checking of database field value accessors" 0)
|
||||
option(WITHOUT_METRICS "Disable metrics reporting (i.e. InfluxDB and Grafana)" 0)
|
||||
option(WITH_DETAILED_METRICS "Enable detailed metrics reporting (i.e. time each session takes to update)" 0)
|
||||
|
||||
IsDynamicLinkingRequired(WITH_DYNAMIC_LINKING_FORCED)
|
||||
IsDynamicLinkingModulesRequired(WITH_DYNAMIC_LINKING_FORCED)
|
||||
|
||||
@ -156,6 +156,18 @@ if(WITH_STRICT_DATABASE_TYPE_CHECKS)
|
||||
add_definitions(-DACORE_STRICT_DATABASE_TYPE_CHECKS)
|
||||
endif()
|
||||
|
||||
if(WITHOUT_METRICS)
|
||||
message("")
|
||||
message(" *** WITHOUT_METRICS - WARNING!")
|
||||
message(" *** Please note that this will disable all metrics output (i.e. InfluxDB and Grafana)")
|
||||
add_definitions(-DWITHOUT_METRICS)
|
||||
elseif (WITH_DETAILED_METRICS)
|
||||
message("")
|
||||
message(" *** WITH_DETAILED_METRICS - WARNING!")
|
||||
message(" *** Please note that this will enable detailed metrics output (i.e. time each session takes to update)")
|
||||
add_definitions(-DWITH_DETAILED_METRICS)
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
message("")
|
||||
message(" *** WITH_DYNAMIC_LINKING - INFO!")
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "MapTree.h"
|
||||
#include "Errors.h"
|
||||
#include "Log.h"
|
||||
#include "Metric.h"
|
||||
#include "ModelInstance.h"
|
||||
#include "VMapDefinitions.h"
|
||||
#include "VMapMgr2.h"
|
||||
@ -452,6 +453,10 @@ namespace VMAP
|
||||
{
|
||||
iLoadedTiles[packTileID(tileX, tileY)] = false;
|
||||
}
|
||||
|
||||
METRIC_EVENT("map_events", "LoadMapTile",
|
||||
"Map: " + std::to_string(iMapID) + " TileX: " + std::to_string(tileX) + " TileY: " + std::to_string(tileY));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -518,6 +523,9 @@ namespace VMAP
|
||||
}
|
||||
}
|
||||
iLoadedTiles.erase(tile);
|
||||
|
||||
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)
|
||||
|
||||
343
src/common/Metric/Metric.cpp
Normal file
343
src/common/Metric/Metric.cpp
Normal file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 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 Affero 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 "Common.h"
|
||||
#include "Config.h"
|
||||
#include "DeadlineTimer.h"
|
||||
#include "Log.h"
|
||||
#include "Strand.h"
|
||||
#include "Util.h"
|
||||
#include "Tokenize.h"
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
Metric::Metric()
|
||||
{
|
||||
}
|
||||
|
||||
Metric::~Metric()
|
||||
{
|
||||
}
|
||||
|
||||
Metric* Metric::instance()
|
||||
{
|
||||
static Metric instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void Metric::Initialize(std::string const& realmName, Acore::Asio::IoContext& ioContext, std::function<void()> overallStatusLogger)
|
||||
{
|
||||
_dataStream = std::make_unique<boost::asio::ip::tcp::iostream>();
|
||||
_realmName = FormatInfluxDBTagValue(realmName);
|
||||
_batchTimer = std::make_unique<Acore::Asio::DeadlineTimer>(ioContext);
|
||||
_overallStatusTimer = std::make_unique<Acore::Asio::DeadlineTimer>(ioContext);
|
||||
_overallStatusLogger = overallStatusLogger;
|
||||
LoadFromConfigs();
|
||||
}
|
||||
|
||||
bool Metric::Connect()
|
||||
{
|
||||
auto& stream = static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream());
|
||||
stream.connect(_hostname, _port);
|
||||
|
||||
auto error = stream.error();
|
||||
if (error)
|
||||
{
|
||||
FMT_LOG_ERROR("metric", "Error connecting to '{}:{}', disabling Metric. Error message: {}",
|
||||
_hostname, _port, error.message());
|
||||
|
||||
_enabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
stream.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Metric::LoadFromConfigs()
|
||||
{
|
||||
bool previousValue = _enabled;
|
||||
_enabled = sConfigMgr->GetOption<bool>("Metric.Enable", false);
|
||||
_updateInterval = sConfigMgr->GetOption<int32>("Metric.Interval", 10);
|
||||
|
||||
if (_updateInterval < 1)
|
||||
{
|
||||
FMT_LOG_ERROR("metric", "'Metric.Interval' config set to {}, overriding to 1.", _updateInterval);
|
||||
_updateInterval = 1;
|
||||
}
|
||||
|
||||
_overallStatusTimerInterval = sConfigMgr->GetOption<int32>("Metric.OverallStatusInterval", 1);
|
||||
if (_overallStatusTimerInterval < 1)
|
||||
{
|
||||
FMT_LOG_ERROR("metric", "'Metric.OverallStatusInterval' config set to {}, overriding to 1.", _overallStatusTimerInterval);
|
||||
_overallStatusTimerInterval = 1;
|
||||
}
|
||||
|
||||
_thresholds.clear();
|
||||
std::vector<std::string> thresholdSettings = sConfigMgr->GetKeysByString("Metric.Threshold.");
|
||||
for (std::string const& thresholdSetting : thresholdSettings)
|
||||
{
|
||||
int64 thresholdValue = sConfigMgr->GetOption<int64>(thresholdSetting, 0);
|
||||
std::string thresholdName = thresholdSetting.substr(strlen("Metric.Threshold."));
|
||||
_thresholds[thresholdName] = thresholdValue;
|
||||
}
|
||||
|
||||
// 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->GetOption<std::string>("Metric.ConnectionInfo", "");
|
||||
if (connectionInfo.empty())
|
||||
{
|
||||
FMT_LOG_ERROR("metric", "'Metric.ConnectionInfo' not specified in configuration file.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string_view> tokens = Acore::Tokenize(connectionInfo, ';', true);
|
||||
if (tokens.size() != 3)
|
||||
{
|
||||
FMT_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();
|
||||
}
|
||||
}
|
||||
|
||||
bool Metric::ShouldLog(std::string const& category, int64 value) const
|
||||
{
|
||||
auto threshold = _thresholds.find(category);
|
||||
|
||||
if (threshold == _thresholds.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return value >= threshold->second;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (MetricTag const& tag : data->Tags)
|
||||
batchedData << "," << tag.first << "=" << FormatInfluxDBTagValue(tag.second);
|
||||
|
||||
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 << " " << 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 (!GetDataStream().good() && !Connect())
|
||||
return;
|
||||
|
||||
GetDataStream() << "POST " << "/write?db=" << _databaseName << " HTTP/1.1\r\n";
|
||||
GetDataStream() << "Host: " << _hostname << ":" << _port << "\r\n";
|
||||
GetDataStream() << "Accept: */*\r\n";
|
||||
GetDataStream() << "Content-Type: application/octet-stream\r\n";
|
||||
GetDataStream() << "Content-Transfer-Encoding: binary\r\n";
|
||||
|
||||
GetDataStream() << "Content-Length: " << std::to_string(batchedData.tellp()) << "\r\n\r\n";
|
||||
GetDataStream() << batchedData.rdbuf();
|
||||
|
||||
std::string http_version;
|
||||
GetDataStream() >> http_version;
|
||||
unsigned int status_code = 0;
|
||||
GetDataStream() >> status_code;
|
||||
|
||||
if (status_code != 204)
|
||||
{
|
||||
FMT_LOG_ERROR("metric", "Error sending data, returned HTTP code: {}", status_code);
|
||||
}
|
||||
|
||||
// Read and ignore the status description
|
||||
std::string status_description;
|
||||
std::getline(GetDataStream(), status_description);
|
||||
|
||||
// Read headers
|
||||
std::string header;
|
||||
|
||||
while (std::getline(GetDataStream(), header) && header != "\r")
|
||||
{
|
||||
if (header == "Connection: close\r")
|
||||
{
|
||||
static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()).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
|
||||
{
|
||||
static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()).close();
|
||||
MetricData* data;
|
||||
|
||||
// Clear the queue
|
||||
while (_queuedData.Dequeue(data))
|
||||
{
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Metric::Unload()
|
||||
{
|
||||
// Send what's queued only if IoContext is stopped (so only on shutdown)
|
||||
if (_enabled && Acore::Asio::get_io_context(*_batchTimer).stopped())
|
||||
{
|
||||
_enabled = false;
|
||||
SendBatch();
|
||||
}
|
||||
|
||||
_batchTimer->cancel();
|
||||
_overallStatusTimer->cancel();
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::string Metric::FormatInfluxDBValue(bool value)
|
||||
{
|
||||
return value ? "t" : "f";
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::string Metric::FormatInfluxDBValue(T value)
|
||||
{
|
||||
return std::to_string(value) + 'i';
|
||||
}
|
||||
|
||||
std::string Metric::FormatInfluxDBValue(std::string const& value)
|
||||
{
|
||||
return '"' + boost::replace_all_copy(value, "\"", "\\\"") + '"';
|
||||
}
|
||||
|
||||
std::string Metric::FormatInfluxDBValue(char const* value)
|
||||
{
|
||||
return FormatInfluxDBValue(std::string(value));
|
||||
}
|
||||
|
||||
std::string Metric::FormatInfluxDBValue(double value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
|
||||
std::string Metric::FormatInfluxDBValue(float value)
|
||||
{
|
||||
return FormatInfluxDBValue(double(value));
|
||||
}
|
||||
|
||||
std::string Metric::FormatInfluxDBTagValue(std::string const& value)
|
||||
{
|
||||
// ToDo: should handle '=' and ',' characters too
|
||||
return boost::replace_all_copy(value, " ", "\\ ");
|
||||
}
|
||||
|
||||
std::string Metric::FormatInfluxDBValue(std::chrono::nanoseconds value)
|
||||
{
|
||||
return FormatInfluxDBValue(std::chrono::duration_cast<Milliseconds>(value).count());
|
||||
}
|
||||
|
||||
template AC_COMMON_API std::string Metric::FormatInfluxDBValue(int8);
|
||||
template AC_COMMON_API std::string Metric::FormatInfluxDBValue(uint8);
|
||||
template AC_COMMON_API std::string Metric::FormatInfluxDBValue(int16);
|
||||
template AC_COMMON_API std::string Metric::FormatInfluxDBValue(uint16);
|
||||
template AC_COMMON_API std::string Metric::FormatInfluxDBValue(int32);
|
||||
template AC_COMMON_API std::string Metric::FormatInfluxDBValue(uint32);
|
||||
template AC_COMMON_API std::string Metric::FormatInfluxDBValue(int64);
|
||||
template AC_COMMON_API std::string Metric::FormatInfluxDBValue(uint64);
|
||||
227
src/common/Metric/Metric.h
Normal file
227
src/common/Metric/Metric.h
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 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 Affero 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 "Define.h"
|
||||
#include "Duration.h"
|
||||
#include "MPSCQueue.h"
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace Acore::Asio
|
||||
{
|
||||
class IoContext;
|
||||
class DeadlineTimer;
|
||||
}
|
||||
|
||||
enum MetricDataType
|
||||
{
|
||||
METRIC_DATA_VALUE,
|
||||
METRIC_DATA_EVENT
|
||||
};
|
||||
|
||||
typedef std::pair<std::string, std::string> MetricTag;
|
||||
|
||||
struct MetricData
|
||||
{
|
||||
std::string Category;
|
||||
SystemTimePoint Timestamp;
|
||||
MetricDataType Type;
|
||||
std::vector<MetricTag> Tags;
|
||||
|
||||
// LogValue-specific fields
|
||||
std::string Value;
|
||||
|
||||
// LogEvent-specific fields
|
||||
std::string Title;
|
||||
std::string Text;
|
||||
};
|
||||
|
||||
class AC_COMMON_API Metric
|
||||
{
|
||||
private:
|
||||
std::iostream& GetDataStream() { return *_dataStream; }
|
||||
std::unique_ptr<std::iostream> _dataStream;
|
||||
MPSCQueue<MetricData> _queuedData;
|
||||
std::unique_ptr<Acore::Asio::DeadlineTimer> _batchTimer;
|
||||
std::unique_ptr<Acore::Asio::DeadlineTimer> _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;
|
||||
std::unordered_map<std::string, int64> _thresholds;
|
||||
|
||||
bool Connect();
|
||||
void SendBatch();
|
||||
void ScheduleSend();
|
||||
void ScheduleOverallStatusLog();
|
||||
|
||||
static std::string FormatInfluxDBValue(bool value);
|
||||
|
||||
template <class T>
|
||||
static std::string FormatInfluxDBValue(T value);
|
||||
|
||||
static std::string FormatInfluxDBValue(std::string const& value);
|
||||
static std::string FormatInfluxDBValue(char const* value);
|
||||
static std::string FormatInfluxDBValue(double value);
|
||||
static std::string FormatInfluxDBValue(float value);
|
||||
static std::string FormatInfluxDBValue(std::chrono::nanoseconds value);
|
||||
|
||||
static std::string FormatInfluxDBTagValue(std::string const& value);
|
||||
|
||||
// ToDo: should format TagKey and FieldKey too in the same way as TagValue
|
||||
|
||||
public:
|
||||
Metric();
|
||||
~Metric();
|
||||
|
||||
static Metric* instance();
|
||||
|
||||
void Initialize(std::string const& realmName, Acore::Asio::IoContext& ioContext, std::function<void()> overallStatusLogger);
|
||||
void LoadFromConfigs();
|
||||
void Update();
|
||||
bool ShouldLog(std::string const& category, int64 value) const;
|
||||
|
||||
template<class T>
|
||||
void LogValue(std::string const& category, T value, std::vector<MetricTag> tags)
|
||||
{
|
||||
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);
|
||||
data->Tags = std::move(tags);
|
||||
|
||||
_queuedData.Enqueue(data);
|
||||
}
|
||||
|
||||
void LogEvent(std::string const& category, std::string const& title, std::string const& description);
|
||||
|
||||
void Unload();
|
||||
bool IsEnabled() const { return _enabled; }
|
||||
};
|
||||
|
||||
#define sMetric Metric::instance()
|
||||
|
||||
template<typename LoggerType>
|
||||
class MetricStopWatch
|
||||
{
|
||||
public:
|
||||
MetricStopWatch(LoggerType&& loggerFunc) :
|
||||
_logger(std::forward<LoggerType>(loggerFunc)),
|
||||
_startTime(sMetric->IsEnabled() ? std::chrono::steady_clock::now() : TimePoint())
|
||||
{
|
||||
}
|
||||
|
||||
~MetricStopWatch()
|
||||
{
|
||||
if (sMetric->IsEnabled())
|
||||
_logger(_startTime);
|
||||
}
|
||||
|
||||
private:
|
||||
LoggerType _logger;
|
||||
TimePoint _startTime;
|
||||
};
|
||||
|
||||
template<typename LoggerType>
|
||||
MetricStopWatch<LoggerType> MakeMetricStopWatch(LoggerType&& loggerFunc)
|
||||
{
|
||||
return { std::forward<LoggerType>(loggerFunc) };
|
||||
}
|
||||
|
||||
#define METRIC_TAG(name, value) { name, value }
|
||||
|
||||
#define METRIC_DO_CONCAT(a, b) a##b
|
||||
#define METRIC_CONCAT(a, b) METRIC_DO_CONCAT(a, b)
|
||||
#define METRIC_UNIQUE_NAME(name) METRIC_CONCAT(name, __LINE__)
|
||||
|
||||
#if defined PERFORMANCE_PROFILING || defined WITHOUT_METRICS
|
||||
#define METRIC_EVENT(category, title, description) ((void)0)
|
||||
#define METRIC_VALUE(category, value, ...) ((void)0)
|
||||
#define METRIC_TIMER(category, ...) ((void)0)
|
||||
#define METRIC_DETAILED_EVENT(category, title, description) ((void)0)
|
||||
#define METRIC_DETAILED_TIMER(category, ...) ((void)0)
|
||||
#define METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) ((void)0)
|
||||
#else
|
||||
#if AC_PLATFORM != AC_PLATFORM_WINDOWS
|
||||
#define METRIC_EVENT(category, title, description) \
|
||||
do { \
|
||||
if (sMetric->IsEnabled()) \
|
||||
sMetric->LogEvent(category, title, description); \
|
||||
} while (0)
|
||||
#define METRIC_VALUE(category, value, ...) \
|
||||
do { \
|
||||
if (sMetric->IsEnabled()) \
|
||||
sMetric->LogValue(category, value, { __VA_ARGS__ }); \
|
||||
} while (0)
|
||||
#else
|
||||
#define 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 METRIC_VALUE(category, value, ...) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:4127)) \
|
||||
do { \
|
||||
if (sMetric->IsEnabled()) \
|
||||
sMetric->LogValue(category, value, { __VA_ARGS__ }); \
|
||||
} while (0) \
|
||||
__pragma(warning(pop))
|
||||
#endif
|
||||
#define METRIC_TIMER(category, ...) \
|
||||
MetricStopWatch METRIC_UNIQUE_NAME(__ac_metric_stop_watch) = MakeMetricStopWatch([&](TimePoint start) \
|
||||
{ \
|
||||
sMetric->LogValue(category, std::chrono::steady_clock::now() - start, { __VA_ARGS__ }); \
|
||||
});
|
||||
#if defined WITH_DETAILED_METRICS
|
||||
#define METRIC_DETAILED_TIMER(category, ...) \
|
||||
MetricStopWatch METRIC_UNIQUE_NAME(__ac_metric_stop_watch) = MakeMetricStopWatch([&](TimePoint start) \
|
||||
{ \
|
||||
int64 duration = int64(std::chrono::duration_cast<Milliseconds>(std::chrono::steady_clock::now() - start).count()); \
|
||||
if (sMetric->ShouldLog(category, duration)) \
|
||||
sMetric->LogValue(category, duration, { __VA_ARGS__ }); \
|
||||
});
|
||||
#define METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) METRIC_TIMER(category, __VA_ARGS__)
|
||||
#define METRIC_DETAILED_EVENT(category, title, description) METRIC_EVENT(category, title, description)
|
||||
#else
|
||||
#define METRIC_DETAILED_EVENT(category, title, description) ((void)0)
|
||||
#define METRIC_DETAILED_TIMER(category, ...) ((void)0)
|
||||
#define METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // METRIC_H__
|
||||
@ -51,6 +51,11 @@ public:
|
||||
return _queue.empty();
|
||||
}
|
||||
|
||||
size_t Size() const
|
||||
{
|
||||
return _queue.size();
|
||||
}
|
||||
|
||||
bool Pop(T& value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_queueLock);
|
||||
|
||||
@ -430,6 +430,12 @@ void DatabaseWorkerPool<T>::Enqueue(SQLOperation* op)
|
||||
_queue->Push(op);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
size_t DatabaseWorkerPool<T>::QueueSize() const
|
||||
{
|
||||
return _queue->Size();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* DatabaseWorkerPool<T>::GetFreeConnection()
|
||||
{
|
||||
|
||||
@ -213,6 +213,8 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t QueueSize() const;
|
||||
|
||||
private:
|
||||
uint32 OpenConnections(InternalIndex type, uint8 numConnections);
|
||||
|
||||
|
||||
@ -29,12 +29,14 @@
|
||||
#include "GuildMgr.h"
|
||||
#include "Language.h"
|
||||
#include "Log.h"
|
||||
#include "Metric.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Pet.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerDump.h"
|
||||
#include "QueryHolder.h"
|
||||
#include "Realm.h"
|
||||
#include "ReputationMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
@ -43,15 +45,14 @@
|
||||
#include "SocialMgr.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "StringConvert.h"
|
||||
#include "Tokenize.h"
|
||||
#include "Transport.h"
|
||||
#include "UpdateMask.h"
|
||||
#include "Util.h"
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "QueryHolder.h"
|
||||
#include "StringConvert.h"
|
||||
#include "Tokenize.h"
|
||||
|
||||
#ifdef ELUNA
|
||||
#include "LuaEngine.h"
|
||||
@ -1087,6 +1088,8 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
|
||||
pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);
|
||||
sScriptMgr->OnFirstLogin(pCurrChar);
|
||||
}
|
||||
|
||||
METRIC_EVENT("player_events", "Login", pCurrChar->GetName());
|
||||
}
|
||||
|
||||
void WorldSession::HandlePlayerLoginToCharInWorld(Player* pCurrChar)
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "LFGMgr.h"
|
||||
#include "Map.h"
|
||||
#include "MapInstanced.h"
|
||||
#include "Metric.h"
|
||||
#include "Object.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectMgr.h"
|
||||
@ -868,6 +869,14 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
HandleDelayedVisibility();
|
||||
|
||||
sScriptMgr->OnMapUpdate(this, t_diff);
|
||||
|
||||
METRIC_VALUE("map_creatures", uint64(GetObjectsStore().Size<Creature>()),
|
||||
METRIC_TAG("map_id", std::to_string(GetId())),
|
||||
METRIC_TAG("map_instanceid", std::to_string(GetInstanceId())));
|
||||
|
||||
METRIC_VALUE("map_gameobjects", uint64(GetObjectsStore().Size<GameObject>()),
|
||||
METRIC_TAG("map_id", std::to_string(GetId())),
|
||||
METRIC_TAG("map_instanceid", std::to_string(GetInstanceId())));
|
||||
}
|
||||
|
||||
void Map::HandleDelayedVisibility()
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "LFGMgr.h"
|
||||
#include "Map.h"
|
||||
#include "MapUpdater.h"
|
||||
#include "Metric.h"
|
||||
|
||||
class UpdateRequest
|
||||
{
|
||||
@ -39,9 +40,11 @@ public:
|
||||
|
||||
void call() override
|
||||
{
|
||||
METRIC_TIMER("map_update_time_diff", METRIC_TAG("map_id", std::to_string(m_map.GetId())));
|
||||
m_map.Update(m_diff, s_diff);
|
||||
m_updater.update_finished();
|
||||
}
|
||||
|
||||
private:
|
||||
Map& m_map;
|
||||
MapUpdater& m_updater;
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "Geometry.h"
|
||||
#include "Log.h"
|
||||
#include "Map.h"
|
||||
#include "Metric.h"
|
||||
#include "MMapFactory.h"
|
||||
#include "MMapMgr.h"
|
||||
#include "PathGenerator.h"
|
||||
@ -61,6 +62,8 @@ bool PathGenerator::CalculatePath(float x, float y, float z, float destX, float
|
||||
if (!Acore::IsValidMapCoord(destX, destY, destZ) || !Acore::IsValidMapCoord(x, y, z))
|
||||
return false;
|
||||
|
||||
METRIC_DETAILED_EVENT("mmap_events", "CalculatePath", "");
|
||||
|
||||
G3D::Vector3 dest(destX, destY, destZ);
|
||||
SetEndPosition(dest);
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "Hyperlinks.h"
|
||||
#include "Log.h"
|
||||
#include "MapMgr.h"
|
||||
#include "Metric.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Opcodes.h"
|
||||
@ -319,6 +320,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
OpcodeClient opcode = static_cast<OpcodeClient>(packet->GetOpcode());
|
||||
ClientOpcodeHandler const* opHandle = opcodeTable[opcode];
|
||||
|
||||
METRIC_DETAILED_TIMER("worldsession_update_opcode_time", METRIC_TAG("opcode", opHandle->Name));
|
||||
|
||||
try
|
||||
{
|
||||
switch (opHandle->Status)
|
||||
@ -441,6 +444,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
|
||||
_recvQueue.readd(requeuePackets.begin(), requeuePackets.end());
|
||||
|
||||
METRIC_VALUE("processed_packets", processedPackets);
|
||||
|
||||
if (!updater.ProcessUnsafe()) // <=> updater is of type MapSessionFilter
|
||||
{
|
||||
// Send time sync packet every 10s.
|
||||
@ -671,6 +676,8 @@ void WorldSession::LogoutPlayer(bool save)
|
||||
//! Call script hook before deletion
|
||||
sScriptMgr->OnPlayerLogout(_player);
|
||||
|
||||
METRIC_EVENT("player_events", "Logout", _player->GetName());
|
||||
|
||||
LOG_INFO("entities.player", "Account: %d (IP: %s) Logout Character:[%s] (%s) Level: %d",
|
||||
GetAccountId(), GetRemoteAddress().c_str(), _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), _player->getLevel());
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@
|
||||
#include "LootMgr.h"
|
||||
#include "MMapFactory.h"
|
||||
#include "MapMgr.h"
|
||||
#include "Metric.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Opcodes.h"
|
||||
#include "OutdoorPvPMgr.h"
|
||||
@ -437,6 +438,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
}
|
||||
|
||||
sLog->LoadFromConfig();
|
||||
sMetric->LoadFromConfigs();
|
||||
}
|
||||
|
||||
// Set realm id and enable db logging
|
||||
@ -2107,10 +2109,13 @@ void World::SetInitialWorldSettings()
|
||||
}
|
||||
|
||||
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
|
||||
|
||||
LOG_INFO("server.loading", " ");
|
||||
LOG_INFO("server.loading", "WORLD: World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000)); // outError for red color in console
|
||||
LOG_INFO("server.loading", " ");
|
||||
|
||||
METRIC_EVENT("events", "World initialized", "World initialized in " + std::to_string(startupDuration / 60000) + " minutes " + std::to_string((startupDuration % 60000) / 1000) + " seconds");
|
||||
|
||||
if (sConfigMgr->isDryRun())
|
||||
{
|
||||
LOG_INFO("server.loading", "AzerothCore dry run completed, terminating.");
|
||||
@ -2199,6 +2204,8 @@ void World::LoadAutobroadcasts()
|
||||
/// Update the World !
|
||||
void World::Update(uint32 diff)
|
||||
{
|
||||
METRIC_TIMER("world_update_time_total");
|
||||
|
||||
m_updateTime = diff;
|
||||
|
||||
if (m_int_configs[CONFIG_INTERVAL_LOG_UPDATE])
|
||||
@ -2238,26 +2245,45 @@ void World::Update(uint32 diff)
|
||||
///- Update the game time and check for shutdown time
|
||||
_UpdateGameTime();
|
||||
|
||||
/// Handle daily quests reset time
|
||||
if (m_gameTime > m_NextDailyQuestReset)
|
||||
ResetDailyQuests();
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Check quest reset times"));
|
||||
|
||||
/// Handle weekly quests reset time
|
||||
if (m_gameTime > m_NextWeeklyQuestReset)
|
||||
ResetWeeklyQuests();
|
||||
/// Handle daily quests reset time
|
||||
if (m_gameTime > m_NextDailyQuestReset)
|
||||
{
|
||||
ResetDailyQuests();
|
||||
}
|
||||
|
||||
/// Handle monthly quests reset time
|
||||
if (m_gameTime > m_NextMonthlyQuestReset)
|
||||
ResetMonthlyQuests();
|
||||
/// Handle weekly quests reset time
|
||||
if (m_gameTime > m_NextWeeklyQuestReset)
|
||||
{
|
||||
ResetWeeklyQuests();
|
||||
}
|
||||
|
||||
/// Handle monthly quests reset time
|
||||
if (m_gameTime > m_NextMonthlyQuestReset)
|
||||
{
|
||||
ResetMonthlyQuests();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_gameTime > m_NextRandomBGReset)
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Reset random BG"));
|
||||
ResetRandomBG();
|
||||
}
|
||||
|
||||
if (m_gameTime > m_NextCalendarOldEventsDeletionTime)
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Delete old calendar events"));
|
||||
CalendarDeleteOldEvents();
|
||||
}
|
||||
|
||||
if (m_gameTime > m_NextGuildReset)
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Reset guild cap"));
|
||||
ResetGuildCap();
|
||||
}
|
||||
|
||||
// pussywizard:
|
||||
// acquire mutex now, this is kind of waiting for listing thread to finish it's work (since it can't process next packet)
|
||||
@ -2269,6 +2295,8 @@ void World::Update(uint32 diff)
|
||||
// pussywizard: handle auctions when the timer has passed
|
||||
if (m_timers[WUPDATE_AUCTIONS].Passed())
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update expired auctions"));
|
||||
|
||||
m_timers[WUPDATE_AUCTIONS].Reset();
|
||||
|
||||
// pussywizard: handle expired auctions, auctions expired when realm was offline are also handled here (not during loading when many required things aren't loaded yet)
|
||||
@ -2283,8 +2311,13 @@ void World::Update(uint32 diff)
|
||||
mail_expire_check_timer = m_gameTime + 6 * 3600;
|
||||
}
|
||||
|
||||
UpdateSessions(diff);
|
||||
{
|
||||
/// <li> Handle session updates when the timer has passed
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions"));
|
||||
UpdateSessions(diff);
|
||||
}
|
||||
}
|
||||
|
||||
// end of section with mutex
|
||||
AsyncAuctionListingMgr::SetAuctionListingAllowed(true);
|
||||
|
||||
@ -2300,6 +2333,8 @@ void World::Update(uint32 diff)
|
||||
{
|
||||
if (m_timers[WUPDATE_CLEANDB].Passed())
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Clean logs table"));
|
||||
|
||||
m_timers[WUPDATE_CLEANDB].Reset();
|
||||
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_OLD_LOGS);
|
||||
@ -2311,33 +2346,58 @@ void World::Update(uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
sLFGMgr->Update(diff, 0); // pussywizard: remove obsolete stuff before finding compatibility during map update
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update LFG 0"));
|
||||
sLFGMgr->Update(diff, 0); // pussywizard: remove obsolete stuff before finding compatibility during map update
|
||||
}
|
||||
|
||||
sMapMgr->Update(diff);
|
||||
///- Update objects when the timer has passed (maps, transport, creatures, ...)
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update maps"));
|
||||
sMapMgr->Update(diff);
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_AUTOBROADCAST))
|
||||
{
|
||||
if (m_timers[WUPDATE_AUTOBROADCAST].Passed())
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Send autobroadcast"));
|
||||
m_timers[WUPDATE_AUTOBROADCAST].Reset();
|
||||
SendAutoBroadcast();
|
||||
}
|
||||
}
|
||||
|
||||
sBattlegroundMgr->Update(diff);
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update battlegrounds"));
|
||||
sBattlegroundMgr->Update(diff);
|
||||
}
|
||||
|
||||
sOutdoorPvPMgr->Update(diff);
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update outdoor pvp"));
|
||||
sOutdoorPvPMgr->Update(diff);
|
||||
}
|
||||
|
||||
sBattlefieldMgr->Update(diff);
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update battlefields"));
|
||||
sBattlefieldMgr->Update(diff);
|
||||
}
|
||||
|
||||
sLFGMgr->Update(diff, 2); // pussywizard: handle created proposals
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update LFG 2"));
|
||||
sLFGMgr->Update(diff, 2); // pussywizard: handle created proposals
|
||||
}
|
||||
|
||||
// execute callbacks from sql queries that were queued recently
|
||||
ProcessQueryCallbacks();
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Process query callbacks"));
|
||||
// execute callbacks from sql queries that were queued recently
|
||||
ProcessQueryCallbacks();
|
||||
}
|
||||
|
||||
/// <li> Update uptime table
|
||||
if (m_timers[WUPDATE_UPTIME].Passed())
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update uptime"));
|
||||
|
||||
uint32 tmpDiff = uint32(m_gameTime - m_startTime);
|
||||
uint32 maxOnlinePlayers = GetMaxPlayerCount();
|
||||
|
||||
@ -2356,6 +2416,7 @@ void World::Update(uint32 diff)
|
||||
///- Erase corpses once every 20 minutes
|
||||
if (m_timers[WUPDATE_CORPSES].Passed())
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Remove old corpses"));
|
||||
m_timers[WUPDATE_CORPSES].Reset();
|
||||
sMapMgr->DoForAllMaps([](Map* map)
|
||||
{
|
||||
@ -2366,6 +2427,7 @@ void World::Update(uint32 diff)
|
||||
///- Process Game events when necessary
|
||||
if (m_timers[WUPDATE_EVENTS].Passed())
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update game events"));
|
||||
m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed
|
||||
uint32 nextGameEvent = sGameEventMgr->Update();
|
||||
m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);
|
||||
@ -2375,6 +2437,7 @@ void World::Update(uint32 diff)
|
||||
///- Ping to keep MySQL connections alive
|
||||
if (m_timers[WUPDATE_PINGDB].Passed())
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Ping MySQL"));
|
||||
m_timers[WUPDATE_PINGDB].Reset();
|
||||
LOG_DEBUG("sql.driver", "Ping MySQL to keep connection alive");
|
||||
CharacterDatabase.KeepAlive();
|
||||
@ -2382,15 +2445,34 @@ void World::Update(uint32 diff)
|
||||
WorldDatabase.KeepAlive();
|
||||
}
|
||||
|
||||
// update the instance reset times
|
||||
sInstanceSaveMgr->Update();
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update instance reset times"));
|
||||
// update the instance reset times
|
||||
sInstanceSaveMgr->Update();
|
||||
}
|
||||
|
||||
// And last, but not least handle the issued cli commands
|
||||
ProcessCliCommands();
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Process cli commands"));
|
||||
// And last, but not least handle the issued cli commands
|
||||
ProcessCliCommands();
|
||||
}
|
||||
|
||||
sScriptMgr->OnWorldUpdate(diff);
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update world scripts"));
|
||||
sScriptMgr->OnWorldUpdate(diff);
|
||||
}
|
||||
|
||||
SavingSystemMgr::Update(diff);
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update saving system"));
|
||||
SavingSystemMgr::Update(diff);
|
||||
}
|
||||
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update metrics"));
|
||||
// Stats logger update
|
||||
sMetric->Update();
|
||||
METRIC_VALUE("update_time_diff", diff);
|
||||
}
|
||||
}
|
||||
|
||||
void World::ForceGameEventUpdate()
|
||||
@ -2710,10 +2792,18 @@ void World::SendServerMessage(ServerMessageType type, const char* text, Player*
|
||||
|
||||
void World::UpdateSessions(uint32 diff)
|
||||
{
|
||||
///- Add new sessions
|
||||
WorldSession* sess = nullptr;
|
||||
while (addSessQueue.next(sess))
|
||||
AddSession_ (sess);
|
||||
{
|
||||
METRIC_DETAILED_NO_THRESHOLD_TIMER("world_update_time",
|
||||
METRIC_TAG("type", "Add sessions"),
|
||||
METRIC_TAG("parent_type", "Update sessions"));
|
||||
|
||||
///- Add new sessions
|
||||
WorldSession* sess = nullptr;
|
||||
while (addSessQueue.next(sess))
|
||||
{
|
||||
AddSession_(sess);
|
||||
}
|
||||
}
|
||||
|
||||
///- Then send an update signal to remaining ones
|
||||
for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)
|
||||
@ -2745,6 +2835,9 @@ void World::UpdateSessions(uint32 diff)
|
||||
continue;
|
||||
}
|
||||
|
||||
[[maybe_unused]] uint32 currentSessionId = itr->first;
|
||||
METRIC_DETAILED_TIMER("world_update_sessions_time", METRIC_TAG("account_id", std::to_string(currentSessionId)));
|
||||
|
||||
if (!pSession->Update(diff, updater))
|
||||
{
|
||||
if (!RemoveQueuedPlayer(pSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
|
||||
|
||||
@ -219,6 +219,10 @@ public:
|
||||
handler->PSendSysMessage("Using World DB Revision: %s", sWorld->GetWorldDBRevision());
|
||||
handler->PSendSysMessage("Using Character DB Revision: %s", sWorld->GetCharacterDBRevision());
|
||||
handler->PSendSysMessage("Using Auth DB Revision: %s", sWorld->GetAuthDBRevision());
|
||||
|
||||
handler->PSendSysMessage("LoginDatabase queue size: %zu", LoginDatabase.QueueSize());
|
||||
handler->PSendSysMessage("CharacterDatabase queue size: %zu", CharacterDatabase.QueueSize());
|
||||
handler->PSendSysMessage("WorldDatabase queue size: %zu", WorldDatabase.QueueSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include "GitRevision.h"
|
||||
#include "IoContext.h"
|
||||
#include "MapMgr.h"
|
||||
#include "Metric.h"
|
||||
#include "MySQLThreading.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "OpenSSLCrypto.h"
|
||||
@ -288,6 +289,22 @@ int main(int argc, char** argv)
|
||||
|
||||
LoadRealmInfo(*ioContext);
|
||||
|
||||
sMetric->Initialize(realm.Name, *ioContext, []()
|
||||
{
|
||||
METRIC_VALUE("online_players", sWorld->GetPlayerCount());
|
||||
METRIC_VALUE("db_queue_login", uint64(LoginDatabase.QueueSize()));
|
||||
METRIC_VALUE("db_queue_character", uint64(CharacterDatabase.QueueSize()));
|
||||
METRIC_VALUE("db_queue_world", uint64(WorldDatabase.QueueSize()));
|
||||
});
|
||||
|
||||
METRIC_EVENT("events", "Worldserver started", "");
|
||||
|
||||
std::shared_ptr<void> sMetricHandle(nullptr, [](void*)
|
||||
{
|
||||
METRIC_EVENT("events", "Worldserver shutdown", "");
|
||||
sMetric->Unload();
|
||||
});
|
||||
|
||||
// Loading modules configs
|
||||
sConfigMgr->PrintLoadedModulesConfigs();
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
# LOGGING SYSTEM SETTINGS
|
||||
# PACKET SPOOF PROTECTION SETTINGS
|
||||
# DEBUG
|
||||
# METRIC SETTINGS
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
@ -3821,3 +3822,58 @@ Debug.Arena = 0
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# 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
|
||||
|
||||
#
|
||||
# Metric threshold values: Given a metric "name"
|
||||
# Metric.Threshold.name
|
||||
# Description: Skips sending statistics with a value lower than the config value.
|
||||
# If the threshold is commented out, the metric will be ignored.
|
||||
# Only metrics logged with METRIC_DETAILED_TIMER in the sources are affected.
|
||||
# Disabled by default. Requires WITH_DETAILED_METRICS CMake flag.
|
||||
#
|
||||
# Format: Value as integer
|
||||
#
|
||||
|
||||
#Metric.Threshold.world_update_sessions_time = 100
|
||||
#Metric.Threshold.worldsession_update_opcode_time = 50
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user