6 Commits

Author SHA1 Message Date
489db10506 version 2023-10-12 16:20:29 -07:00
31fa09e478 Merge branch 'develop' 2023-10-12 16:20:15 -07:00
3c43a2bc20 finalize for release 2023-10-12 16:17:25 -07:00
85ed597711 fixes for prod 2023-10-12 16:14:05 -07:00
40b5a3d26f small reorg, some improvements, readme updates
- fix hemtt config to copy example
- add measurements table in Readme
- ENTITY COUNTS
  - re add side tags
  - use `side group _x` for units and players
  - fix players_connected and add headless_clients
- get `_allUserInfos = allUsers apply {getUserInfo _x} select {count _x > 0};` from main loop and use in entity counts and player performance
2023-10-10 18:17:18 -07:00
9ccb6fd3cd Merge branch 'master' into develop 2023-10-10 18:04:00 -07:00
15 changed files with 131 additions and 30 deletions

3
.gitignore vendored
View File

@@ -8,5 +8,6 @@
ifxmetrics.config.json
.hemttout
influxdb
influxdb/data
influxdb/config
releases

View File

@@ -9,7 +9,8 @@ git_hash=6 # Default: 8
[files]
include=[
"ifxmetrics.config.json",
"ifxmetrics.config.example.json",
# "ifxmetrics.config.json", # used for copying during debugging
"LICENSE",
"README.md",
"mod.cpp",

View File

@@ -105,6 +105,58 @@ Grafana is a dashboarding tool. It is used to display the data from InfluxDB. A
---
## CORE METRICS
These metrics will be gathered by default every `refreshRateMs` milliseconds.
| Bucket | Measurement | Tags | Field |
| --- | --- | --- | --- |
| server_performance | fps | profile=`profileName` world=`worldName` server=`serverName` | fps_avg=`diag_fps` |
| server_performance | fps | ... | fps_min=`diag_fpsMin` |
| server_performance | running_scripts | ... | spawn=`diag_activeScripts#0` |
| server_performance | running_scripts | ... | execVM=`diag_activeScripts#1` |
| server_performance | running_scripts | ... | exec=`diag_activeScripts#2` |
| server_performance | running_scripts | ... | execFSM=`diag_activeScripts#3` |
| server_performance | running_scripts | ... | pfh=`count CBA_common_perFrameHandlerArray \|\| 0` |
| server_performance | entities_remote | ... + side=`WEST`,`EAST`, etc | units_alive=`{side group _x isEqualTo _thisSide && not (local _x)} count _allUnits` |
| server_performance | entities_remote | ... + side=`WEST`,`EAST`, etc | units_dead=`{side group _x isEqualTo _thisSide && not (local _x)} count _allDeadMen` |
| server_performance | entities_remote | ... + side=`WEST`,`EAST`, etc | groups_total=`{side _x isEqualTo _thisSide && not (local _x)} count _allGroups` |
| server_performance | entities_remote | ... + side=`WEST`,`EAST`, etc | vehicles_total=`{side _x isEqualTo _thisSide && not (local _x) && !(_x isKindOf "WeaponHolderSimulated")} count _vehicles` |
| server_performance | entities_remote | ... + side=`WEST`,`EAST`, etc | vehicles_weaponholder=`{side _x isEqualTo _thisSide && not (local _x) && (_x isKindOf "WeaponHolderSimulated")} count _vehicles` |
| server_performance | entities_local | ... + side=`WEST`,`EAST`, etc | units_alive=`{side group _x isEqualTo _thisSide && (local _x)} count _allUnits` |
| server_performance | entities_local | ... + side=`WEST`,`EAST`, etc | units_dead=`{side group _x isEqualTo _thisSide && (local _x)} count _allDeadMen` |
| server_performance | entities_local | ... + side=`WEST`,`EAST`, etc | groups_total=`{side _x isEqualTo _thisSide && (local _x)} count _allGroups` |
| server_performance | entities_local | ... + side=`WEST`,`EAST`, etc | vehicles_total=`{side _x isEqualTo _thisSide && (local _x) && !(_x isKindOf "WeaponHolderSimulated")} count _vehicles` |
| server_performance | entities_local | ... + side=`WEST`,`EAST`, etc | vehicles_weaponholder=`{side _x isEqualTo _thisSide && (local _x) && (_x isKindOf "WeaponHolderSimulated")} count _vehicles` |
| server_performance | entities_global | ... + side=`WEST`,`EAST`, etc | units_alive=`{side group _x isEqualTo _thisSide} count _allUnits` |
| server_performance | entities_global | ... + side=`WEST`,`EAST`, etc | units_dead=`{side group _x isEqualTo _thisSide} count _allDeadMen` |
| server_performance | entities_global | ... + side=`WEST`,`EAST`, etc | groups_total=`{side _x isEqualTo _thisSide} count _allGroups` |
| server_performance | entities_global | ... + side=`WEST`,`EAST`, etc | vehicles_total=`{side _x isEqualTo _thisSide && !(_x isKindOf "WeaponHolderSimulated")} count _vehicles` |
| server_performance | entities_global | ... + side=`WEST`,`EAST`, etc | vehicles_weaponholder=`{side _x isEqualTo _thisSide && (_x isKindOf "WeaponHolderSimulated")} count _vehicles` |
| server_performance | entities_global | ... + side=`WEST`,`EAST`, etc | players_alive=`{side group _x isEqualTo _thisSide && alive _x} count (call BIS_fnc_listPlayers)` |
| server_performance | entities_global | ... + side=`WEST`,`EAST`, etc | players_dead=`{side group _x isEqualTo _thisSide && !alive _x} count (call BIS_fnc_listPlayers)` |
| server_performance | player_count | ... | players_connected=`count (_allUserInfos select {_x#7 isEqualTo false})` |
| server_performance | player_count | ... | headless_clients_connected=`count (_allUserInfos select {_x#7 isEqualTo true})` |
| player_performance | network | ... + playerUID=`getUserInfo#2`, playerName=`getUserInfo#3` | avgPing=`getUserInfo#9#0` |
| player_performance | network | ... + playerUID=`getUserInfo#2`, playerName=`getUserInfo#3` | avgBandwidth=`getUserInfo#9#1` |
| player_performance | network | ... + playerUID=`getUserInfo#2`, playerName=`getUserInfo#3` | desync=`getUserInfo#9#2` |
| mission_data | server_time | ... | diag_tickTime=`diag_tickTime` |
| mission_data | server_time | ... | serverTime=`time` |
| mission_data | server_time | ... | timeMultiplier=`timeMultiplier` |
| mission_data | server_time | ... | accTime=`accTime` |
| mission_data | weather | ... | fog=`fog` |
| mission_data | weather | ... | overcast=`overcast` |
| mission_data | weather | ... | rain=`rain` |
| mission_data | weather | ... | humidity=`humidity` |
| mission_data | weather | ... | waves=`waves` |
| mission_data | weather | ... | windDir=`windDir` |
| mission_data | weather | ... | windStr=`windStr` |
| mission_data | weather | ... | gusts=`gusts` |
| mission_data | weather | ... | lightnings=`lightnings` |
| mission_data | weather | ... | moonIntensity=`moonIntensity` |
| mission_data | weather | ... | moonPhase=`moonPhase` |
| mission_data | weather | ... | sunOrMoon=`sunOrMoon` |
## BUILDING
Set an environment variable in your terminal with the desired extension build version. It defaults to "DEVELOPMENT".
@@ -127,13 +179,19 @@ Run this from the project root.
docker pull x1unix/go-mingw:1.20
# Compile x64 Windows DLL
docker run --rm -it -v ${PWD}:/go/work -w /go/work -e GOARCH=amd64 -e CGO_ENABLED=1 x1unix/go-mingw:1.20 go build -o ./ifxmetrics_x64.dll -buildmode=c-shared -ldflags "-w -s -X main.EXTENSION_VERSION=`"$IFXMETRICS_BUILD_VER`"" ./extension/cmd
docker run --rm -it -v ${PWD}/extension/IFXMetrics:/go/work -w /go/work -e GOARCH=amd64 -e CGO_ENABLED=1 x1unix/go-mingw:1.20 go build -o ./dist/ifxmetrics_x64.dll -buildmode=c-shared -ldflags "-w -s -X main.EXTENSION_VERSION=$IFXMETRICS_BUILD_VER" ./cmd
Move-Item -Path ./extension/IFXMetrics/dist/ifxmetrics_x64.dll -Destination ./ifxmetrics_x64.dll -Force
# Compile x86 Windows DLL
docker run --rm -it -v ${PWD}:/go/work -w /go/work -e GOARCH=386 -e CGO_ENABLED=1 x1unix/go-mingw:1.20 go build -o ./ifxmetrics.dll -buildmode=c-shared -ldflags "-w -s -X main.EXTENSION_VERSION=`"$IFXMETRICS_BUILD_VER`"" ./extension/cmd
docker run --rm -it -v ${PWD}/extension/IFXMetrics:/go/work -w /go/work -e GOARCH=386 -e CGO_ENABLED=1 x1unix/go-mingw:1.20 go build -o ./dist/ifxmetrics.dll -buildmode=c-shared -ldflags "-w -s -X main.EXTENSION_VERSION=$IFXMETRICS_BUILD_VER" ./cmd
Move-Item -Path ./extension/IFXMetrics/dist/ifxmetrics.dll -Destination ./ifxmetrics.dll -Force
# Compile x64 Windows EXE
docker run --rm -it -v ${PWD}:/go/work -w /go/work -e GOARCH=amd64 -e CGO_ENABLED=1 x1unix/go-mingw:1.20 go build -o ./ifxmetrics_x64.exe -ldflags "-w -s -X main.EXTENSION_VERSION=`"$IFXMETRICS_BUILD_VER`"" ./extension/cmd
docker run --rm -it -v ${PWD}/extension/IFXMetrics:/go/work -w /go/work -e GOARCH=amd64 -e CGO_ENABLED=1 x1unix/go-mingw:1.20 go build -o ./dist/ifxmetrics_x64.exe -ldflags "-w -s -X main.EXTENSION_VERSION=$IFXMETRICS_BUILD_VER" ./cmd
Move-Item -Path ./extension/IFXMetrics/dist/ifxmetrics_x64.exe -Destination ./ifxmetrics_x64.exe -Force
```
### EXTENSION: COMPILING FOR LINUX
@@ -144,10 +202,15 @@ Run this from the project root.
docker build -t indifox926/build-a3go:linux-so -f ./build/Dockerfile.build .
# Compile x64 Linux .so
docker run --rm -it -v ${PWD}:/app -e GOOS=linux -e GOARCH=amd64 -e CGO_ENABLED=1 indifox926/build-a3go:linux-so go build -o ./ifxmetrics_x64.so -linkshared -ldflags "-w -s -X main.EXTENSION_VERSION=${IFXMETRICS_BUILD_VER}" ./extension/cmd
docker run --rm -it -v ${PWD}/extension/IFXMetrics:/app -e GOOS=linux -e GOARCH=amd64 -e CGO_ENABLED=1 indifox926/build-a3go:linux-so go build -o ./dist/ifxmetrics_x64.so -linkshared -ldflags "-w -s -X main.EXTENSION_VERSION=${IFXMETRICS_BUILD_VER}" ./cmd
Move-Item -Path ./extension/IFXMetrics/dist/ifxmetrics_x64.so -Destination ./ifxmetrics_x64.so -Force
# Compile x86 Linux .so
docker run --rm -it -v ${PWD}:/app -e GOOS=linux -e GOARCH=386 -e CGO_ENABLED=1 indifox926/build-a3go:linux-so go build -o ./ifxmetrics.so -linkshared -ldflags "-w -s -X main.EXTENSION_VERSION=${IFXMETRICS_BUILD_VER}" ./extension/cmd
docker run --rm -it -v ${PWD}/extension/IFXMetrics:/app -e GOOS=linux -e GOARCH=386 -e CGO_ENABLED=1 indifox926/build-a3go:linux-so go build -o ./dist/ifxmetrics.so -linkshared -ldflags "-w -s -X main.EXTENSION_VERSION=${IFXMETRICS_BUILD_VER}" ./cmd
Move-Item -Path ./extension/IFXMetrics/dist/ifxmetrics.so -Destination ./ifxmetrics.so -Force
```
### ADDON: COMPILE USING HEMTT

View File

@@ -1,5 +1,9 @@
#include "script_component.hpp"
params [
["_allUserInfos", [], [[]]]
];
private _hashesOut = [];
private _allUnits = allUnits;
@@ -10,18 +14,20 @@ private _allPlayers = call BIS_fnc_listPlayers;
{
private _thisSide = _x;
private _thisSideStr = _thisSide call BIS_fnc_sideNameUnlocalized;
private _tags = +GVARMAIN(standardTags);
_tags pushBack ["side", _thisSideStr];
// Number of remote units
_hashesOut pushBack ([
["bucket", "server_performance"],
["measurement", "entities_remote"],
["tags", GVARMAIN(standardTags)],
["tags", _tags],
["fields", [
["units_alive", {
side _x isEqualTo _thisSide &&
side group _x isEqualTo _thisSide &&
not (local _x)
} count _allUnits],
["units_dead", {
side _x isEqualTo _thisSide &&
side group _x isEqualTo _thisSide &&
not (local _x)
} count _allDeadMen],
["groups_total", {
@@ -45,14 +51,14 @@ private _allPlayers = call BIS_fnc_listPlayers;
_hashesOut pushBack ([
["bucket", "server_performance"],
["measurement", "entities_local"],
["tags", GVARMAIN(standardTags)],
["tags", _tags],
["fields", [
["units_alive", {
side _x isEqualTo _thisSide &&
side group _x isEqualTo _thisSide &&
local _x
} count _allUnits],
["units_dead", {
side _x isEqualTo _thisSide &&
side group _x isEqualTo _thisSide &&
local _x
} count _allDeadMen],
["groups_total", {
@@ -78,13 +84,13 @@ private _allPlayers = call BIS_fnc_listPlayers;
_hashesOut pushBack ([
["bucket", "server_performance"],
["measurement", "entities_global"],
["tags", GVARMAIN(standardTags)],
["tags", _tags],
["fields", [
["units_alive", {
side _x isEqualTo _thisSide
side group _x isEqualTo _thisSide
} count _allUnits],
["units_dead", {
side _x isEqualTo _thisSide
side group _x isEqualTo _thisSide
} count _allDeadMen],
["groups_total", {
side _x isEqualTo _thisSide
@@ -98,11 +104,11 @@ private _allPlayers = call BIS_fnc_listPlayers;
(_x isKindOf "WeaponHolderSimulated")
} count _vehicles],
["players_alive", {
side _x isEqualTo _thisSide &&
side group _x isEqualTo _thisSide &&
alive _x
} count _allPlayers],
["players_dead", {
side _x isEqualTo _thisSide &&
side group _x isEqualTo _thisSide &&
!alive _x
} count _allPlayers]
]]
@@ -116,12 +122,8 @@ if (isServer) then {
["measurement", "player_count"],
["tags", GVARMAIN(standardTags)],
["fields", [
["players_connected", {
private _info = getUserInfo (getPlayerId _x);
if (!isNil "_info" && {count _info >= 6}) then {
_info select 7
} else {false}
} count _allPlayers]
["players_connected", count (_allUserInfos select {_x#7 isEqualTo false})],
["headless_clients_connected", count (_allUserInfos select {_x#7 isEqualTo true})]
]]
]);
};

View File

@@ -1,5 +1,9 @@
#include "script_component.hpp"
params [
["_allUserInfos", [], [[]]]
];
private _hashesOut = [];
{
_x params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit"];
@@ -23,6 +27,6 @@ private _hashesOut = [];
["desync", _desync]
]]
]);
} forEach (allUsers apply {getUserInfo _x});
} forEach _allUserInfos;
_hashesOut;

View File

@@ -5,7 +5,11 @@ class CfgPatches {
units[] = {};
weapons[] = {};
requiredVersion = 2.10;
requiredAddons[] = {};
requiredAddons[] = {
"cba_main",
"cba_xeh",
"cba_settings"
};
author[] = {"IndigoFox"};
authorUrl = "https://github.com/indig0fox/IFXMetrics";
};

View File

@@ -24,19 +24,22 @@ GVARMAIN(captureLoop) = [
]
];
// getUserInfo for all users
private _allUserInfos = allUsers apply {getUserInfo _x} select {count _x > 0};
// entity_count returns an array of hashMap
{
GVARMAIN(extensionName) callExtension [
":INFLUX:WRITE:",
[_x]
];
} forEach (call EFUNC(capture,entity_count));
} forEach ([_allUserInfos] call EFUNC(capture,entity_count));
{
GVARMAIN(extensionName) callExtension [
":INFLUX:WRITE:",
[_x]
];
} forEach (call EFUNC(capture,player_performance));
} forEach ([_allUserInfos] call EFUNC(capture,player_performance));
["DEBUG", format[
"Processed primary data loop in %1 ms",

View File

@@ -1,7 +1,7 @@
#define MAJOR 2
#define MINOR 0
#define PATCH 0
#define BUILD 20231009
#define PATCH 1
#define BUILD 20231012
#define VERSION 2.0
#define VERSION_STR MAJOR##.##MINOR##.##PATCH##.##BUILD

View File

@@ -319,4 +319,7 @@ func main() {
// s := settings.Active.Get("cbaEventHandlers")
// // return the custom cba event handlers as an arma hashmap
// fmt.Println(a3interface.ToArmaHashMap(s))
fmt.Println("IFXMetrics extension started. Version: " + EXTENSION_VERSION)
fmt.Scanln()
}

View File

@@ -0,0 +1,20 @@
version: '3.8'
services:
influxdb:
image: influxdb:latest
container_name: influxdb
restart: always
ports:
- 8086:8086
volumes:
- ./data:/var/lib/influxdb2
- ./config:/etc/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=exampleuser
- DOCKER_INFLUXDB_INIT_PASSWORD=dfaow3ho9i7funa0w3nv
- DOCKER_INFLUXDB_INIT_ORG=ifx-metrics
- DOCKER_INFLUXDB_INIT_BUCKET=test-bucket
- DOCKER_INFLUXDB_INIT_RETENTION=1w
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=f0982q3ahfu8yawbo27w8fb986ba90b0wb2f