-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathindex.js
137 lines (114 loc) · 4.64 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
const prometheus = require('prom-client');
const register = prometheus.register;
const prometheusTimeout = GetConvarInt('prometheus_timeout', 5000);
const authEnabled = GetConvarInt('prometheus_auth_enabled', 0);
const authLogin = GetConvar('prometheus_login', 'admin');
const authPassword = GetConvar('prometheus_password', 'admin');
const authorizationHeader = 'Basic ' + new Buffer(authLogin + ':' + authPassword).toString('base64');
// Collect some default FiveM metrics
const playerCount = new prometheus.Gauge({ name: 'fxs_player_count', help: 'Number of connected players.' });
const playerConnections = new prometheus.Counter({ name: 'fxs_player_connections', help: 'Number of player connections.' });
const playerDisconnections = new prometheus.Counter({ name: 'fxs_player_disconnections', help: 'Number of player disconnections.' });
const averageLatency = new prometheus.Gauge({ name: 'fxs_average_player_latency', help: 'Average player latency.' });
const latencyHistogram = new prometheus.Histogram({ name: 'fxs_players_latency', help: 'Players latency.', buckets: [10, 20, 50, 70, 100, 120, 150, 160, 200] });
const minPlayerPing = new prometheus.Gauge({ name: 'fxs_min_player_ping', help: 'Minimum player ping.' });
const maxPlayerPing = new prometheus.Gauge({ name: 'fxs_max_player_ping', help: 'Maximum player ping.' });
const objectCountG = new prometheus.Gauge({ name: 'fxs_object_count', help: 'Current object count.'});
const pedCountG = new prometheus.Gauge({ name: 'fxs_ped_count', help: 'Current ped count.'});
const vehicleCountG = new prometheus.Gauge({ name: 'fxs_vehicle_count', help: 'Current vehicle count.'});
const eventsSentToClient = new prometheus.Gauge({ name: 'fxs_events_client', help: 'Events sent to client from server'});
const eventsSentToServer = new prometheus.Gauge({name : 'fxs_events_server', help: 'Events sent from server to server'});
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
let sCount = 0;
let cCount = 0;
async function gatherEvents() {
emit("prometheus:_gatherEventCount", function(serverCount, clientCount) {
sCount += serverCount;
cCount += clientCount;
});
await delay(1000);
eventsSentToClient.set(cCount);
eventsSentToServer.set(sCount);
setTimeout(gatherEvents, 1000);
}
setTimeout(gatherEvents, 1000);
setInterval(async () => {
const numIndices = GetNumPlayerIndices();
let cumulativeLatency = 0;
let minPing, maxPing;
const objectCount = GetAllObjects().length;
const pedCount = GetAllPeds().length;
const vehicleCount = GetAllVehicles().length;
objectCountG.set(objectCount);
pedCountG.set(pedCount);
vehicleCountG.set(vehicleCount);
for (let playerIndex = 0; playerIndex < numIndices; playerIndex++) {
const player = GetPlayerFromIndex(playerIndex);
const playerPing = GetPlayerPing(player);
cumulativeLatency += playerPing;
if (!minPing || minPing > playerPing) {
minPing = playerPing;
}
if (!maxPing || maxPing < playerPing) {
maxPing = playerPing;
}
latencyHistogram.observe(playerPing);
}
playerCount.set(numIndices);
if (numIndices > 0) {
averageLatency.set(cumulativeLatency / numIndices);
minPlayerPing.set(minPing);
maxPlayerPing.set(maxPing);
} else {
averageLatency.set(0);
minPlayerPing.set(0);
maxPlayerPing.set(0);
}
}, prometheusTimeout);
on('playerConnecting', (playerName, setKickReason, tempPlayer) => {
playerConnections.inc();
});
on('playerDropped', (player, disconnectReason) => {
playerDisconnections.inc();
});
/**
* Server event
* @event prometheus:addMetric
*
* @param {string} type - The metric type, i.e. Gauge.
* @param {string} name - The metric name.
* @param {string} description - The metric description.
* @param {function} cb - A callback function to update the metric with a method name (i.e. set) and a value.
*/
on('prometheus:addMetric', (type, name, description, cb) => {
if (!prometheus[type]) {
console.error(`[FiveM Prometheus] Invalid metric type ${type} for ${name}`);
return;
}
let metric = new prometheus[type]({ name: name, help: description });
setInterval(() => {
cb((methodName, value) => {
if (metric[methodName]) {
metric[methodName](value);
}
});
}, prometheusTimeout);
});
on('prometheus:_getMetrics', (cb) => {
cb(register.metrics());
});
on('prometheus:_resetGauges', () => {
sCount = 0;
cCount = 0;
})
// Don't use this for now, there is a deadlock somewhere :/
/*SetHttpHandler((req, res) => {
const authorizedRequest = !authEnabled || req.headers['Authorization'] === authorizationHeader;
if (req.path === '/metrics' && authorizedRequest) {
res.send(register.metrics());
} else {
res.send('Route /' + GetCurrentResourceName() + req.path + ' not found.');
}
});*/