Merge branch 'develop' into implement-settings

This commit is contained in:
2023-04-14 14:58:27 -07:00
10 changed files with 270 additions and 97 deletions

View File

@@ -2,7 +2,7 @@ class CfgPatches {
class RangerMetrics { class RangerMetrics {
units[] = {}; units[] = {};
weapons[] = {}; weapons[] = {};
requiredVersion = 0.1; requiredVersion = 2.10;
requiredAddons[] = {}; requiredAddons[] = {};
author[] = {"EagleTrooper","Gary","IndigoFox"}; author[] = {"EagleTrooper","Gary","IndigoFox"};
authorUrl = "http://example.com"; authorUrl = "http://example.com";
@@ -10,6 +10,13 @@ class CfgPatches {
}; };
class CfgFunctions { class CfgFunctions {
class RangerMetrics_callback {
class functions {
file = "\RangerMetrics\functions\callbackHandlers";
class callbackHandler {};
class loadSettings {};
};
};
class RangerMetrics_event { class RangerMetrics_event {
class functions { class functions {
file = "\RangerMetrics\functions\capture\EHOnly"; file = "\RangerMetrics\functions\capture\EHOnly";
@@ -23,7 +30,7 @@ class CfgFunctions {
class MarkerUpdated {}; class MarkerUpdated {};
class milsim_serverEfficiency {}; class milsim_serverEfficiency {};
}; };
} };
class RangerMetrics_cDefinitions { class RangerMetrics_cDefinitions {
class functions { class functions {
file = "\RangerMetrics\functions\captureDefinitions"; file = "\RangerMetrics\functions\captureDefinitions";
@@ -62,7 +69,6 @@ class CfgFunctions {
class log {}; class log {};
class queue {}; class queue {};
class send {}; class send {};
class callbackHandler {};
class sendClientPoll {}; class sendClientPoll {};
class startServerPoll {}; class startServerPoll {};
class classHandlers {}; class classHandlers {};

View File

@@ -0,0 +1,45 @@
params ["_name", "_function", "_data"];
if !(_name == "RangerMetrics") exitWith {};
// Validate data param
if (isNil "_data") then {_data = ""};
if (_data isEqualTo "") exitWith {
[
format ["Callback empty data: %1", _function],
"WARN"
] call RangerMetrics_fnc_log;
false;
};
// Parse response from string array
private "_response";
try {
diag_log format ["Raw callback: %1: %2", _function, _data];
_response = parseSimpleArray _data;
} catch {
[
format ["Callback invalid data: %1: %2", _function, _data],
"WARN"
] call RangerMetrics_fnc_log;
};
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";
} else {
_response call RangerMetrics_fnc_log;
};
};
case "loadSettings": {
// Load settings
_response call RangerMetrics_callback_fnc_loadSettings;
};
default {
_response call RangerMetrics_fnc_log;
}
}

View File

@@ -0,0 +1,33 @@
private _data = _this;
switch (_data select 0) do {
case "CREATED SETTINGS": {
[
"settings.json did not exist and has been created - you will need to update it with your own settings before the addon will initialize further.",
"ERROR"
] call RangerMetrics_fnc_log;
};
case "SETTINGS LOADED": {
RangerMetrics_settings = createHashMapFromArray (_data # 1);
[
format [
"Settings loaded successfully from JSON. %1",
RangerMetrics_settings
],
"INFO"
] call RangerMetrics_fnc_log;
// send server profile name to all clients with JIP, so HC or player reporting knows what server it's connected to
if (isServer) then {
["RangerMetrics_serverProfileName", profileName] remoteExecCall ["setVariable", 0, true];
RangerMetrics_serverProfileName = profileName;
};
};
default {
[
_data select 0,
"INFO"
] call RangerMetrics_fnc_log;
};
};

View File

@@ -3,6 +3,8 @@ if (!RangerMetrics_run) exitWith {};
params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit", ["_jip", false]]; params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit", ["_jip", false]];
// _networkInfo params ["_avgPing", "_avgBandwidth", "_desync"]; // _networkInfo params ["_avgPing", "_avgBandwidth", "_desync"];
private _fields = [ private _fields = [
["string", "playerID", _playerID], ["string", "playerID", _playerID],
["string", "ownerId", _ownerId], ["string", "ownerId", _ownerId],
@@ -14,6 +16,55 @@ private _fields = [
["bool", "isJip", _jip] ["bool", "isJip", _jip]
]; ];
try {
// Get Squad Info of Player
(squadParams _unit) params [
"_squadInfo",
"_unitInfo",
"_squadId",
"_a3unitsId"
];
// For each section, we'll define the format and save to fields
_squadInfoDataFormat = [
"squadNick",
"squadName",
"squadEmail",
"squadWeb",
"squadLogo",
"squadTitle"
];
{
_fields pushBack [
"string",
_squadInfoDataFormat select _forEachIndex,
_squadInfo select _forEachIndex
];
} forEach _squadInfoDataFormat;
_unitInfoDataFormat =[
"unitUid",
"unitName",
"unitFullName",
"unitICQ",
"unitRemark"
];
{
_fields pushBack [
"string",
_unitInfoDataFormat select _forEachIndex,
_unitInfo select _forEachIndex
];
} forEach _unitInfoDataFormat;
} catch {
// If we fail to get squad info, we'll just skip it
[format["Failed to get squad info for %1", _playerUID]] call RangerMetrics_fnc_log;
};
// Role description // Role description
private _roleDescription = roleDescription _unit; private _roleDescription = roleDescription _unit;
if (_roleDescription isNotEqualTo "") then { if (_roleDescription isNotEqualTo "") then {

View File

@@ -5,7 +5,7 @@ params [
]; ];
if (isNull _unit) exitWith {false}; if (isNull _unit) exitWith {false};
// if (!isPlayer _unit) exitWith {}; if (!isPlayer _unit) exitWith {};
// do not check more than once every 15 seconds // do not check more than once every 15 seconds
_checkDelay = 15; _checkDelay = 15;
@@ -47,7 +47,6 @@ if (_unitId isEqualTo -1) exitWith {false};
"unit_loadout", "unit_loadout",
[ [
["string", "playerUID", _playerUID], ["string", "playerUID", _playerUID],
["string", "unitId", str _unitId],
["string", "format", "className"] ["string", "format", "className"]
], ],
_classItemCounts, _classItemCounts,

View File

@@ -1,14 +0,0 @@
params ["_name", "_function", "_data"];
if (_name == "RangerMetrics") then {
if (isNil "_data") then {_data = ""};
try {
if (_data isEqualType "") exitWith {
_data = parseSimpleArray _data;
_data call RangerMetrics_fnc_log;
};
diag_log format ["Callback unsupported type: %1: %2", _function, _data];
} catch {
_data = format ["%1", _data];
};
};

View File

@@ -19,49 +19,18 @@ RangerMetrics_sendBatchHandle = scriptNull;
[format ["CBA detected: %1", RangerMetrics_cbaPresent]] call RangerMetrics_fnc_log; [format ["CBA detected: %1", RangerMetrics_cbaPresent]] call RangerMetrics_fnc_log;
["Initializing v0.1"] call RangerMetrics_fnc_log; ["Initializing v0.1"] call RangerMetrics_fnc_log;
// Create listener - extension calls are async, so we need to listen for the response
// load settings from extension / settings.json addMissionEventHandler [
private _settingsLoaded = "RangerMetrics" callExtension "loadSettings"; "ExtensionCallback",
// if (isNil "_settingsLoaded") exitWith { RangerMetrics_callback_fnc_callbackHandler
// ["Extension not found, disabling"] call RangerMetrics_fnc_log;
// RangerMetrics_run = false;
// };
if (_settingsLoaded isEqualTo [] || _settingsLoaded isEqualTo "") exitWith {
["Failed to load settings, exiting", "ERROR"] call RangerMetrics_fnc_log;
};
_settingsLoaded = parseSimpleArray (_settingsLoaded);
[format["Settings loaded: %1", _settingsLoaded]] call RangerMetrics_fnc_log;
RangerMetrics_settings = createHashMap;
RangerMetrics_settings set [
"influxDB",
createHashMapFromArray [
["host", _settingsLoaded#1],
["org", _settingsLoaded#2]
]
];
RangerMetrics_settings set [
"arma3",
createHashMapFromArray [
["refreshRateMs", _settingsLoaded#3]
]
]; ];
// Deinit to start fresh. See callback handler for the remainder of async init code
"RangerMetrics" callExtension "deinitExtension";
// connect to DB, extension is now ready
private _dbConnection = "RangerMetrics" callExtension "connectToInflux";
if (_dbConnection isEqualTo "") exitWith {
["Failed to connect to InfluxDB, disabling"] call RangerMetrics_fnc_log;
};
_response = parseSimpleArray _dbConnection;
(_response) call RangerMetrics_fnc_log;
systemChat str _response;
// send server profile name to all clients with JIP, so HC or player reporting knows what server it's connected to if (true) exitWith {};
if (isServer) then {
["RangerMetrics_serverProfileName", profileName] remoteExecCall ["setVariable", 0, true];
RangerMetrics_serverProfileName = profileName;
};
// define the metrics to capture by sideloading definition files // define the metrics to capture by sideloading definition files
@@ -158,10 +127,7 @@ RangerMetrics_captureDefinitions = createHashMapFromArray [
[] spawn { [] spawn {
sleep 1; sleep 1;
isNil { isNil {
addMissionEventHandler [
"ExtensionCallback",
RangerMetrics_fnc_callbackHandler
];
// set up CBA class inits if CBA loaded // set up CBA class inits if CBA loaded
call RangerMetrics_fnc_classHandlers; call RangerMetrics_fnc_classHandlers;

View File

@@ -10,6 +10,7 @@ classDiagram
Measurement PlayerDisconnected Measurement PlayerDisconnected
Measurement OnUserClientStateChanged Measurement OnUserClientStateChanged
Measurement OnUserAdminStateChanged Measurement OnUserAdminStateChanged
Measurement OnUserKicked
Meausrement HandleChatMessage Meausrement HandleChatMessage
Measurement MPEnded Measurement MPEnded
Measurement EntityCreated Measurement EntityCreated
@@ -19,11 +20,13 @@ classDiagram
Measurement MarkerCreated Measurement MarkerCreated
Measurement MarkerDeleted Measurement MarkerDeleted
Measurement MarkerUpdated Measurement MarkerUpdated
Measurement Service
} }
server_state --> running_mission server_state --> running_mission
class running_mission { class running_mission {
capture: ServerPoll, 60s capture: ServerPoll, 60s
capture: MissionEH, MPEnded
tag string profileName tag string profileName
tag string connectedServer tag string connectedServer
field string onLoadName field string onLoadName
@@ -43,28 +46,34 @@ classDiagram
server_state --> server_time server_state --> server_time
class server_time { class server_time {
tag string profileName capture: ServerPoll, 3s
tag string connectedServer tag string profileName
field float diag_tickTime tag string connectedServer
field int serverTime field float diag_tickTime
field float timeMultiplier field int serverTime
field int accTime field float timeMultiplier
field int accTime
} }
server_state --> running_scripts server_state --> running_scripts
class running_scripts { class running_scripts {
tag string profileName capture: ServerPoll, 3s
tag string connectedServer tag string profileName
field int spawn_total tag string connectedServer
field int execVM_total field int spawn_total
field int exec_total field int execVM_total
field int execFSM_total field int exec_total
field int pfh_total field int execFSM_total
field int pfh_total
} }
server_state --> entities_local server_state --> entities_local
class entities_local { class entities_local {
capture: ServerPoll, 1s (customizable) capture: ServerPoll, 30s
capture: MissionEH, EntityKilled
capture: MissionEH, EntityCreated
capture: MissionEH, GroupCreated
capture: MissionEH, GroupDeleted
tag string profileName tag string profileName
tag string connectedServer tag string connectedServer
field int units_alive field int units_alive
@@ -74,7 +83,11 @@ classDiagram
} }
server_state --> entities_global server_state --> entities_global
class entities_global { class entities_global {
capture: ServerPoll, 1s (customizable) capture: ServerPoll, 30s
capture: MissionEH, EntityKilled
capture: MissionEH, EntityCreated
capture: MissionEH, GroupCreated
capture: MissionEH, GroupDeleted
tag string profileName tag string profileName
tag string connectedServer tag string connectedServer
field int units_alive field int units_alive
@@ -84,7 +97,11 @@ classDiagram
} }
server_state --> entities_remote server_state --> entities_remote
class entities_remote { class entities_remote {
capture: ServerPoll, 1s (customizable) capture: ServerPoll, 30s
capture: MissionEH, EntityKilled
capture: MissionEH, EntityCreated
capture: MissionEH, GroupCreated
capture: MissionEH, GroupDeleted
tag string profileName tag string profileName
tag string connectedServer tag string connectedServer
field int units_alive field int units_alive
@@ -95,7 +112,7 @@ classDiagram
server_state --> server_performance server_state --> server_performance
class server_performance { class server_performance {
capture: ServerPoll, 1s (customizable) capture: ServerPoll, 1s
tag string profileName tag string profileName
tag string connectedServer tag string connectedServer
field string fps_avg field string fps_avg
@@ -128,7 +145,6 @@ classDiagram
Measurement mission_config_file Measurement mission_config_file
Measurement addon_options Measurement addon_options
Measurement mission_parameters Measurement mission_parameters
Measurement visual_settings
} }
config_state --> mission_config_file config_state --> mission_config_file
@@ -254,15 +270,6 @@ classDiagram
field string missionGroup field string missionGroup
} }
config_state --> visual_settings
class visual_settings {
tag string profileName
tag string connectedServer
field string getTIParameters
field string objectViewDistance
}
class player_state class player_state
@@ -272,8 +279,9 @@ classDiagram
capture: MissionEH, OnUserDisconnected capture: MissionEH, OnUserDisconnected
capture: MissionEH, PlayerConnected capture: MissionEH, PlayerConnected
capture: MissionEH, PlayerDisconnected capture: MissionEH, PlayerDisconnected
tag string profileName capture: MissionEH, OnUserKicked
tag string connectedServer tag string connectedServer
tag string playerUID
field string playerID field string playerID
field string ownerId field string ownerId
field string playerUID field string playerUID
@@ -293,9 +301,9 @@ classDiagram
capture: MissionEH, PlayerDisconnected capture: MissionEH, PlayerDisconnected
capture: MissionEH, OnUserClientStateChanged capture: MissionEH, OnUserClientStateChanged
capture: MissionEH, OnUserAdminStateChanged capture: MissionEH, OnUserAdminStateChanged
tag string profileName capture: MissionEH, OnUserKicked
tag string connectedServer tag string connectedServer
field string playerUID tag string playerUID
field int clientStateNumber field int clientStateNumber
field int adminState field int adminState
} }
@@ -303,20 +311,19 @@ classDiagram
player_state --> player_performance player_state --> player_performance
class player_performance { class player_performance {
capture: ServerPoll capture: ServerPoll
tag string profileName
tag string connectedServer tag string connectedServer
field string playerUID tag string playerUID
field float avgPing field float avgPing
field float avgBandwidth field float avgBandwidth
field float desync field float desync
} }
player_state --> unit_loadout player_state --> unit_inventory
class unit_loadout { class unit_inventory {
capture: InventoryClosedEH capture: InventoryClosedEH
tag string profileName
tag string connectedServer tag string connectedServer
field string playerUID tag string playerUID
field string currentWeapon
field string uniform field string uniform
field string vest field string vest
field string backpack field string backpack
@@ -333,6 +340,8 @@ classDiagram
player_state --> unit_state player_state --> unit_state
class unit_state { class unit_state {
capture: UnitEH, GetInMan
capture: UnitEH, GetOutMan
tag string connectedServer tag string connectedServer
tag string playerUID tag string playerUID
field float health field float health
@@ -342,6 +351,9 @@ classDiagram
field bool in_vehicle field bool in_vehicle
field string vehicle_role field string vehicle_role
field float speed_kmh field float speed_kmh
field string unitTraitX
field bool unitTraitY
field int unitTraitZ
} }
class player_events class player_events
@@ -400,4 +412,24 @@ player_events --> Dammaged
field int score field int score
field string object field string object
field string objectclass field string objectclass
}
player_events --> InventoryClosed
class InventoryClosed {
capture: UnitEH, InventoryClosed
tag string connectedServer
tag string playerUID
field string currentWeaponClass
field string uniformClass
field string vestClass
field string backpackClass
field string headgearClass
field string gogglesClass
field string hmdClass
field string primaryWeaponClass
field string primaryWeaponMagazineClass
field string secondaryWeaponClass
field string secondaryWeaponMagazineClass
field string handgunWeaponClass
field string handgunMagazineClass
} }

View File

@@ -0,0 +1,52 @@
[
{
"apiVersion": "influxdata.com/v2alpha1",
"kind": "Bucket",
"metadata": {
"name": "alerting-chaum-a8c001"
},
"spec": {
"name": "config_state"
}
},
{
"apiVersion": "influxdata.com/v2alpha1",
"kind": "Bucket",
"metadata": {
"name": "hardcore-hodgkin-a8c005"
},
"spec": {
"name": "player_state"
}
},
{
"apiVersion": "influxdata.com/v2alpha1",
"kind": "Bucket",
"metadata": {
"name": "objective-curie-a8c003"
},
"spec": {
"name": "player_events"
}
},
{
"apiVersion": "influxdata.com/v2alpha1",
"kind": "Bucket",
"metadata": {
"name": "romantic-blackwell-a8c009"
},
"spec": {
"name": "server_state"
}
},
{
"apiVersion": "influxdata.com/v2alpha1",
"kind": "Bucket",
"metadata": {
"name": "thirsty-leakey-a8c007"
},
"spec": {
"name": "server_events"
}
}
]

View File

@@ -0,0 +1,3 @@
# Requires Influx CLI to be installed. Used to quickly generate a template of buckets to import to an instance for pre-setup.
# https://docs.influxdata.com/influxdb/v2.7/reference/cli/influx/export/
influx export all -f "bucketsTemplate.json" --filter=resourceKind=Bucket