fix RPT spam, allow re-init of capture, change to spawn loop, fix setvar
- add readme too
This commit is contained in:
68
7cavChat.txt
68
7cavChat.txt
@@ -1,68 +0,0 @@
|
||||
Jarvis — Today at 8:23 PM
|
||||
@EagleTrooper let's use this instead
|
||||
to save blowing up the recruiters notifications
|
||||
on recruitment
|
||||
EagleTrooper — Today at 8:23 PM
|
||||
Yeah keep the recruitment clean. I understand Im a recruiter / NCO / admin for the community in involved in.
|
||||
Alright,
|
||||
I am working on developing a dashboard that gives historical stats with our server as well as our missions that run Performance / FPS / Memory Usage / etc. During my research i came across your groups Repo and it appears that you are doing something very similar to what I wanted to do. I did read through just to get an idea unfortunately there was some gaps in the implementation and i was hoping to speak to someone about how it was done with your group as well as if they would be so kind as to provide pointers and insight so that I may implement something very similar.
|
||||
Jarvis — Today at 8:26 PM
|
||||
Do you know how to setup a Grafana/InfluxDB stack?
|
||||
EagleTrooper — Today at 8:27 PM
|
||||
Already have it setup (Background in IT and Cloud Network Engineering).
|
||||
Sweetwater.I — Today at 8:27 PM
|
||||
u can see our dashboard here if u wanna see what cavmetrics extension is outputting.
|
||||
https://metrics.7cav.us/d/NED-gV3Mz/arma3?orgId=1&refresh=10s
|
||||
Jarvis — Today at 8:28 PM
|
||||
It's basically just arma -> influx -> grafana
|
||||
Sweetwater.I — Today at 8:28 PM
|
||||
but yeah, influxdb+grafana is what we do
|
||||
Jarvis — Today at 8:28 PM
|
||||
The cavmetrics addon you see is the arma extension
|
||||
EagleTrooper — Today at 8:28 PM
|
||||
Yep understood the workflow and that was very clear. I believe the piece im missing or dont understand is the dll creation / implementation
|
||||
Jarvis — Today at 8:28 PM
|
||||
If you know influx/grafana, you're 2/3rds of the way there
|
||||
|
||||
Just git clone the cavmetrics repo
|
||||
EagleTrooper — Today at 8:29 PM
|
||||
I believe it was the Arma-Influx?
|
||||
That was the piece that i was not clear on. Unless i was misunderstanding it still required a compiled DLL
|
||||
Jarvis — Today at 8:29 PM
|
||||
the a3_influx dll is inside of the git repo
|
||||
so == a DLL but linux
|
||||
we run our servers on linux
|
||||
EagleTrooper — Today at 8:30 PM
|
||||
Unfortuantly it looks like its a .so
|
||||
Sweetwater.I — Today at 8:30 PM
|
||||
use the arma-influx repo to build the extension
|
||||
EagleTrooper — Today at 8:30 PM
|
||||
Yeah we have windows :/
|
||||
Sweetwater.I — Today at 8:30 PM
|
||||
cavmetrics is what we called the packaged extension.
|
||||
on the repo
|
||||
Jarvis — Today at 8:30 PM
|
||||
https://github.com/7Cav/Arma-Influx
|
||||
GitHub
|
||||
GitHub - 7Cav/Arma-Influx: Arma Extension for sending metrics to In...
|
||||
Arma Extension for sending metrics to InfluxDB. Contribute to 7Cav/Arma-Influx development by creating an account on GitHub.
|
||||
|
||||
Just compile that for dll
|
||||
it's an arma ext written in go
|
||||
Liber.N — Today at 8:31 PM
|
||||
Cavmetrics is an arma addon thats calls to arma influx extension
|
||||
Jarvis — Today at 8:31 PM
|
||||
you'll need to change the makefile on that repo tho
|
||||
EagleTrooper — Today at 8:32 PM
|
||||
does it need to be labeld armago? or a3influx?
|
||||
If that is what your referring to then it appears i do have an understanding of it and something else is missing outside of my imediate understanding and may not have anything you can provide input on. I will review the implementation again and see if I can get any further.
|
||||
I do appreciate the input and help.
|
||||
Jarvis — Today at 8:35 PM
|
||||
no probs, it's a long road but found it worth it in the end
|
||||
|
||||
https://metrics.7cav.us/
|
||||
Specifically - https://metrics.7cav.us/d/NED-gV3Mz/arma3?orgId=1&refresh=10s
|
||||
EagleTrooper — Today at 8:36 PM
|
||||
I will take a look! Keep on Keeping on and again I appreciate the friendly response!
|
||||
Jarvis — Today at 8:36 PM
|
||||
You'll need to update these for your influx db host - https://github.com/7Cav/cav_metrics/blob/dev/%40CavMetrics/addons/CavMetrics/functions/fn_send.sqf#L9-L12
|
||||
@@ -31,7 +31,6 @@ try {
|
||||
|
||||
switch (_function) do {
|
||||
case "deinitExtension": {
|
||||
diag_log format ["RangerMetrics: deinitExtension: %1", _response];
|
||||
// Our first call is deinitExtension. When we received a single "true" value, we can then run init processes for the extension connections.
|
||||
if ((_response select 0) isEqualTo true) then {
|
||||
"RangerMetrics" callExtension "initExtension";
|
||||
@@ -46,6 +45,39 @@ switch (_function) do {
|
||||
// Load settings
|
||||
[_function, _response] call RangerMetrics_callback_fnc_loadSettings;
|
||||
};
|
||||
case "extensionReady": {
|
||||
// deinitialize existing captures
|
||||
if (!isNil "RangerMetrics_allMEH") then {
|
||||
{
|
||||
private _handle = missionNamespace getVariable _x;
|
||||
if (isNil "_handle") then {continue};
|
||||
private _EHName = (_x splitString "_") select 2;
|
||||
removeMissionEventHandler [_EHName, _handle];
|
||||
missionNamespace setVariable [_x, nil];
|
||||
} forEach RangerMetrics_allMEH;
|
||||
};
|
||||
|
||||
if (!isNil "RangerMetrics_allCBA") then {
|
||||
{
|
||||
private _handle = missionNamespace getVariable _x;
|
||||
if (isNil "_handle") then {continue};
|
||||
private _EHName = (_x splitString "_") select 2;
|
||||
[_EHName, _handle] call CBA_fnc_removeEventHandler;
|
||||
missionNamespace setVariable [_x, nil];
|
||||
} forEach RangerMetrics_allCBA;
|
||||
};
|
||||
|
||||
if (!isNil "RangerMetrics_allServerPoll") then {
|
||||
{
|
||||
private _handle = missionNamespace getVariable _x;
|
||||
if (isNil "_handle") then {continue};
|
||||
terminate _handle;
|
||||
missionNamespace setVariable [_x, nil];
|
||||
} forEach RangerMetrics_allServerPoll;
|
||||
};
|
||||
|
||||
call RangerMetrics_fnc_initCapture;
|
||||
};
|
||||
default {
|
||||
_response call RangerMetrics_fnc_log;
|
||||
};
|
||||
|
||||
@@ -16,10 +16,12 @@ if (_function isEqualTo "loadSettingsJSON") exitWith {
|
||||
] call RangerMetrics_fnc_log;
|
||||
|
||||
if (isServer) then {
|
||||
RangerMetrics_serverProfileName = profileName;
|
||||
publicVariable "RangerMetrics_serverProfileName";
|
||||
missionNamespace setVariable [
|
||||
"RangerMetrics_serverProfileName",
|
||||
profileName,
|
||||
true
|
||||
];
|
||||
};
|
||||
call RangerMetrics_fnc_initCapture;
|
||||
};
|
||||
|
||||
switch (_data select 0) do {
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
false;
|
||||
} else {
|
||||
missionNamespace setVariable [
|
||||
("RangerMetrics" + "_CBAEH_" + _settingName),
|
||||
("RangerMetrics" + "_CBAEH_" + _handleName),
|
||||
_handle
|
||||
];
|
||||
true;
|
||||
@@ -81,24 +81,24 @@
|
||||
|
||||
|
||||
|
||||
private _meh = allVariables missionNamespace select {
|
||||
RangerMetrics_allMEH = allVariables missionNamespace select {
|
||||
_x find (toLower "RangerMetrics_MEH_") == 0
|
||||
};
|
||||
private _cba = allVariables missionNamespace select {
|
||||
RangerMetrics_allCBA = allVariables missionNamespace select {
|
||||
_x find (toLower "RangerMetrics_CBAEH_") == 0
|
||||
};
|
||||
private _serverPoll = allVariables missionNamespace select {
|
||||
RangerMetrics_allServerPoll = allVariables missionNamespace select {
|
||||
_x find (toLower "RangerMetrics_serverPoll_") == 0
|
||||
};
|
||||
|
||||
[format ["Mission event handlers: %1", _meh]] call RangerMetrics_fnc_log;
|
||||
[format ["CBA event handlers: %1", _cba]] call RangerMetrics_fnc_log;
|
||||
[format ["Server poll handles: %1", _serverPoll]] call RangerMetrics_fnc_log;
|
||||
[format ["Mission event handlers: %1", RangerMetrics_allMEH]] call RangerMetrics_fnc_log;
|
||||
[format ["CBA event handlers: %1", RangerMetrics_allCBA]] call RangerMetrics_fnc_log;
|
||||
[format ["Server poll handles: %1", RangerMetrics_allServerPoll]] call RangerMetrics_fnc_log;
|
||||
|
||||
|
||||
RangerMetrics_initialized = true;
|
||||
RangerMetrics_run = true;
|
||||
["RangerMetrics_run", true] remoteExecCall ["setVariable", 0];
|
||||
missionNamespace setVariable ["RangerMetrics_initialized", true, true];
|
||||
missionNamespace setVariable ["RangerMetrics_run", true, true];
|
||||
|
||||
|
||||
|
||||
// start sending
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
params [["_text","Log text invalid"], ["_type","INFO"]];
|
||||
params [["_text","Log text invalid"], ["_logType","DEBUG"]];
|
||||
|
||||
if (typeName _this != "ARRAY") exitWith {
|
||||
diag_log format ["RangerMetrics: Invalid log params: %1", _this];
|
||||
@@ -6,18 +6,19 @@ if (typeName _this != "ARRAY") exitWith {
|
||||
if (typeName _text != "STRING") exitWith {
|
||||
diag_log format ["RangerMetrics: Invalid log text: %1", _this];
|
||||
};
|
||||
if (typeName _type != "STRING") exitWith {
|
||||
if (typeName _logType != "STRING") exitWith {
|
||||
diag_log format ["RangerMetrics: Invalid log type: %1", _this];
|
||||
};
|
||||
|
||||
if (_type isEqualTo "DEBUG") then {
|
||||
if (!RangerMetrics_debug) exitWith {};
|
||||
};
|
||||
if (
|
||||
_logType == "DEBUG" &&
|
||||
!(missionNamespace getVariable ["RangerMetrics_debug", false])
|
||||
) exitWith {};
|
||||
|
||||
private _textFormatted = format [
|
||||
"[%1] %2: %3",
|
||||
RangerMetrics_logPrefix,
|
||||
_type,
|
||||
_logType,
|
||||
_text];
|
||||
|
||||
if(isServer) then {
|
||||
|
||||
@@ -20,7 +20,7 @@ RangerMetrics_recordingSettings = createHashMap;
|
||||
|
||||
[format ["Instance name: %1", profileName]] call RangerMetrics_fnc_log;
|
||||
[format ["CBA detected: %1", RangerMetrics_cbaPresent]] call RangerMetrics_fnc_log;
|
||||
["Initializing v0.1"] call RangerMetrics_fnc_log;
|
||||
["Initializing v0.0.2"] call RangerMetrics_fnc_log;
|
||||
|
||||
// Create listener - extension calls are async, so we need to listen for the response
|
||||
addMissionEventHandler [
|
||||
|
||||
@@ -21,7 +21,17 @@ if (_tagContext find "world" > -1) then {
|
||||
_tags pushBack ["string", "world", toLower worldName];
|
||||
};
|
||||
if (_tagContext find "server" > -1) then {
|
||||
_tags pushBack ["string", "connectedServer", RangerMetrics_serverProfileName];
|
||||
private _serverProfile = missionNamespace getVariable [
|
||||
"RangerMetrics_serverProfileName",
|
||||
""
|
||||
];
|
||||
if (_serverProfile isNotEqualTo "") then {
|
||||
_tags pushBack [
|
||||
"string",
|
||||
"connectedServer",
|
||||
_serverProfile
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
private _outTags = _tags apply {
|
||||
|
||||
@@ -12,16 +12,41 @@ if (_interval == 0) exitWith {
|
||||
[_code] call CBA_fnc_execNextFrame;
|
||||
};
|
||||
|
||||
|
||||
private _handle = [{
|
||||
params ["_args", "_idPFH"];
|
||||
_args params ["_refName", "_code"];
|
||||
|
||||
[_code] call CBA_fnc_execNextFrame;
|
||||
|
||||
}, _interval, _this] call CBA_fnc_addPerFrameHandler;
|
||||
|
||||
// run a constant scheduled loop
|
||||
private _runnerVar = "RangerMetrics" + "_serverPollRunner_" + _refName;
|
||||
missionNamespace setVariable [_runnerVar, scriptNull];
|
||||
private _spawnParams = [_refName, _code, _interval, _runnerVar];
|
||||
private _handle = _spawnParams spawn {
|
||||
params ["_refName", "_code", "_interval", "_runnerVar"];
|
||||
while {true} do {
|
||||
if (scriptDone (
|
||||
missionNamespace getVariable _runnerVar
|
||||
)) then {
|
||||
private _handle = [] spawn _code;
|
||||
missionNamespace setVariable [
|
||||
_runnerVar,
|
||||
_handle
|
||||
];
|
||||
};
|
||||
// sleep _interval;
|
||||
sleep 2;
|
||||
};
|
||||
};
|
||||
missionNamespace setVariable [
|
||||
"RangerMetrics" + "_serverPoll_" + _refName,
|
||||
_handle
|
||||
];
|
||||
|
||||
// USE PFH
|
||||
// private _handle = [{
|
||||
// params ["_args", "_idPFH"];
|
||||
// _args params ["_refName", "_code"];
|
||||
|
||||
// [_code] call CBA_fnc_execNextFrame;
|
||||
|
||||
// }, _interval, _this] call CBA_fnc_addPerFrameHandler;
|
||||
|
||||
// missionNamespace setVariable [
|
||||
// "RangerMetrics" + "_serverPoll_" + _refName,
|
||||
// _handle
|
||||
// ];
|
||||
@@ -5,18 +5,19 @@
|
||||
"token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX_AUTH_TOKEN_XXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
"org": "ORG_NAME"
|
||||
},
|
||||
"arma3": {
|
||||
"refreshRateMs": 1000,
|
||||
"debug": false
|
||||
},
|
||||
"timescaledb": {
|
||||
"enabled": false,
|
||||
"connectionUrl": "postgresql://user:pass@host.com:5432",
|
||||
"databaseName": "ranger_metrics",
|
||||
"description": "TimescaleDB is an open-source time-series database built on Postgres. The extension will connect to the maintenance database (postgres) first and create the database it will control with desired name, then shift connections to the newly created database to create the schema and conduct write operations."
|
||||
},
|
||||
"arma3": {
|
||||
"refreshRateMs": 1000,
|
||||
"debug": false
|
||||
},
|
||||
"recordingSettings": {
|
||||
"serverPerformance": {
|
||||
"serverPolls": [
|
||||
{
|
||||
"name": "serverPerformance",
|
||||
"enabled": true,
|
||||
"serverOnly": false,
|
||||
@@ -25,7 +26,7 @@
|
||||
"measurement": "fps",
|
||||
"description": "SERVER/HC POLL. Tracks average and minimum FPS. Polled on server (and HC) at specified interval."
|
||||
},
|
||||
"runningScripts": {
|
||||
{
|
||||
"name": "runningScripts",
|
||||
"enabled": true,
|
||||
"serverOnly": false,
|
||||
@@ -34,7 +35,7 @@
|
||||
"measurement": "running_scripts",
|
||||
"description": "SERVER/HC POLL. Tracks the number of scripts running on the server (and HC). Polled on specified interval."
|
||||
},
|
||||
"entityCount": {
|
||||
{
|
||||
"name": "entityCount",
|
||||
"enabled": true,
|
||||
"serverOnly": false,
|
||||
@@ -43,16 +44,16 @@
|
||||
"measurement": "n/a",
|
||||
"description": "SERVER/HC POLL. Tracks the number of entities on the server. Polled on server (and HC) at specified interval as well as on EntityCreated/EntityRespawned/EntityKilled events. Measurement is static, [entities_local, entities_remote, entities_global]."
|
||||
},
|
||||
"playerPerformance": {
|
||||
{
|
||||
"name": "playerPerformance",
|
||||
"enabled": true,
|
||||
"serverOnly": true,
|
||||
"intervalMs": 3000,
|
||||
"intervalMs": 1000,
|
||||
"bucket": "player_performance",
|
||||
"measurement": "network",
|
||||
"description": "SERVER POLL. User network performance. Tracks average ping, average bandwidth, and desync. Polled by the server at specified interval. Not tracked from headless client."
|
||||
},
|
||||
"serverTime": {
|
||||
{
|
||||
"name": "serverTime",
|
||||
"enabled": true,
|
||||
"serverOnly": true,
|
||||
@@ -61,25 +62,25 @@
|
||||
"measurement": "server_time",
|
||||
"description": "SERVER POLL. Tracks the server time. Always server-only. Runs at specified interval."
|
||||
},
|
||||
"weather": {
|
||||
{
|
||||
"name": "weather",
|
||||
"enabled": true,
|
||||
"serverOnly": true,
|
||||
"intervalMs": 300000,
|
||||
"intervalMs": 120000,
|
||||
"bucket": "mission_data",
|
||||
"measurement": "weather",
|
||||
"description": "SERVER POLL. Tracks the weather on the server. Always server-only. Runs at specified interval."
|
||||
},
|
||||
"viewDistance": {
|
||||
{
|
||||
"name": "viewDistance",
|
||||
"enabled": true,
|
||||
"serverOnly": true,
|
||||
"intervalMs": 300000,
|
||||
"intervalMs": 120000,
|
||||
"bucket": "mission_data",
|
||||
"measurement": "view_distance",
|
||||
"description": "SERVER POSTINIT, MPEnded. Tracks the view distance on the server. Always server-only. Runs at specified interval."
|
||||
},
|
||||
"runningMission": {
|
||||
{
|
||||
"name": "runningMission",
|
||||
"enabled": true,
|
||||
"serverOnly": true,
|
||||
@@ -87,34 +88,14 @@
|
||||
"bucket": "mission_data",
|
||||
"measurement": "running_mission",
|
||||
"description": "SERVER POSTINIT, MPEnded. Tracks the name of the mission running on the server. Always server-only. Runs at the start (and tries at end) of the mission."
|
||||
},
|
||||
"playerStatus": {
|
||||
"name": "playerStatus",
|
||||
"enabled": true,
|
||||
"serverOnly": true,
|
||||
"intervalMs": 0,
|
||||
"bucket": "player_data",
|
||||
"measurement": "client_state",
|
||||
"description": "EH. Tracks players' clientstateNumber, adminState, and profileName on connect/disconnect to server and to mission, as well as when these values change."
|
||||
},
|
||||
"playerIdentity": {
|
||||
"name": "playerIdentity",
|
||||
"enabled": true,
|
||||
"serverOnly": true,
|
||||
"intervalMs": 0,
|
||||
"bucket": "player_data",
|
||||
"measurement": "player_identity",
|
||||
"description": "EH. Tracks players' identity on connect/disconnect to server and to mission, as well as when these values change."
|
||||
},
|
||||
"CBAEventHandlers": {
|
||||
"milsimServerEfficiency": {
|
||||
}
|
||||
],
|
||||
"CBAEventHandlers": [
|
||||
{
|
||||
"name": "milsimServerEfficiency",
|
||||
"enabled": true,
|
||||
"serverOnly": true,
|
||||
"bucket": "server_performance",
|
||||
"measurement": "milsim_server_efficiency",
|
||||
"description": "EVENTHANDLER. Tracks the efficiency of the server."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
56
README.md
56
README.md
@@ -1,3 +1,57 @@
|
||||
# RangerMetrics based off of CAV-Metrics
|
||||
# RangerMetrics - Arma3 InfluxDB Metrics
|
||||
|
||||
Ranger Metrics is used to submit information from the Arma3 Instance to the Influx Database. This uses the ArmaInflux Version complied to a DLL to communicate.
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### Settings.json
|
||||
|
||||
Configure the options in settings.json.
|
||||
|
||||
As of v0.0.2, metrics are captured on a recurring loop in the scheduled environment with a two second pause to allow time. Whether to use CBA Per Frame Handlers that run metric collection less often and in the unscheduled environment has yet to be decided on, as it does lead to longer intervals that are more difficult to graph precisely.
|
||||
|
||||
### InfluxDB
|
||||
|
||||
InfluxDB is a time series database. It is used to store data points with a timestamp.
|
||||
|
||||
#### Required Buckets
|
||||
|
||||
- mission_data
|
||||
- player_data
|
||||
- player_performance
|
||||
- server_events
|
||||
- server_performance
|
||||
|
||||
### Grafana
|
||||
|
||||
Grafana is a dashboarding tool. It is used to display the data from InfluxDB. Import the dashboard from the json file in the root of this addon and set up your datasources appropriately.
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
### Ingame
|
||||
|
||||
#### Toggle Capture On/Off
|
||||
|
||||
Running the following commands in Server Exec will toggle the capture on or off for the server and any Headless Clients. Capture loops will still occur but will exit almost immediately.
|
||||
|
||||
Change the last parameter to false to ONLY target the server when run as Server Exec.
|
||||
|
||||
*This may not apply to raw Event Handler data which goes under `server_events`*
|
||||
|
||||
```sqf
|
||||
// ON
|
||||
missionNamespace setVariable ["RangerMetrics_run", true, true];
|
||||
|
||||
// OFF
|
||||
missionNamespace setVariable ["RangerMetrics_run", false, true];
|
||||
```
|
||||
|
||||
#### Reload Settings.json and recreate all capture loops
|
||||
|
||||
To reload everything while in a game, run `"RangerMetrics" callExtension "deinitExtension";` in Global Exec. This will disconnect any database connections and reset state. Running it Global Exec will cause any client with the addon to run it, which includes Headless Clients.
|
||||
|
||||
When the extension is finished, it will notify Arma via a callback. The addon will then __automatically__ run `"RangerMetrics" callExtension "initExtension";` to reinitialize the extension, to include fetching the new settings, tearing down existing captures, and re-setting up captures with the new settings.
|
||||
|
||||
3237
grafana_dashboard.json
Normal file
3237
grafana_dashboard.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user