@pilaf/backends 1.0.2 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1170 -10
- package/lib/collectors/DockerLogCollector.js +334 -0
- package/lib/collectors/index.js +9 -0
- package/lib/core/CommandRouter.js +154 -0
- package/lib/core/CorrelationStrategy.js +172 -0
- package/lib/core/LogCollector.js +194 -0
- package/lib/core/LogParser.js +125 -0
- package/lib/core/index.js +26 -0
- package/lib/errors/index.js +363 -0
- package/lib/helpers/EventObserver.js +267 -0
- package/lib/helpers/QueryHelper.js +279 -0
- package/lib/helpers/index.js +13 -0
- package/lib/index.js +72 -1
- package/lib/mineflayer-backend.js +266 -1
- package/lib/monitoring/CircularBuffer.js +202 -0
- package/lib/monitoring/LogMonitor.js +303 -0
- package/lib/monitoring/correlations/TagCorrelationStrategy.js +214 -0
- package/lib/monitoring/correlations/UsernameCorrelationStrategy.js +233 -0
- package/lib/monitoring/correlations/index.js +13 -0
- package/lib/monitoring/index.js +16 -0
- package/lib/parsers/MinecraftLogParser.js +512 -0
- package/lib/parsers/PatternRegistry.js +366 -0
- package/lib/parsers/fixtures/minecraft-logs.js +188 -0
- package/lib/parsers/index.js +13 -0
- package/lib/rcon-backend.js +42 -26
- package/package.json +3 -2
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UsernameCorrelationStrategy - Correlates events by player username
|
|
3
|
+
*
|
|
4
|
+
* This correlation strategy groups events by player username to track
|
|
5
|
+
* player sessions across all their activities. Useful for:
|
|
6
|
+
*
|
|
7
|
+
* - Tracking player session lifecycle (join -> actions -> leave)
|
|
8
|
+
* - Monitoring player behavior patterns
|
|
9
|
+
* - Generating per-player statistics
|
|
10
|
+
* - Debugging player-specific issues
|
|
11
|
+
*
|
|
12
|
+
* Example use case:
|
|
13
|
+
* - Player joins: entity.join event with data.player = "Steve"
|
|
14
|
+
* - Player dies: entity.death.slain event with data.player = "Steve"
|
|
15
|
+
* - Player leaves: entity.leave event with data.player = "Steve"
|
|
16
|
+
* - Strategy groups all events under username "Steve"
|
|
17
|
+
*
|
|
18
|
+
* Features:
|
|
19
|
+
* - Configurable username extraction function
|
|
20
|
+
* - Session tracking (start/end times)
|
|
21
|
+
* - Active/inactive session status
|
|
22
|
+
* - Automatic session cleanup on leave
|
|
23
|
+
*
|
|
24
|
+
* Usage Example:
|
|
25
|
+
* const strategy = new UsernameCorrelationStrategy({
|
|
26
|
+
* usernameExtractor: (event) => event.data?.player
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* const joinEvent = { type: 'entity.join', data: { player: 'Steve' } };
|
|
30
|
+
* const correlation = strategy.correlate(joinEvent);
|
|
31
|
+
* // correlation: { username: 'Steve', events: [joinEvent], sessionStart: Date.now(), isActive: true }
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const { EventEmitter } = require('events');
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* UsernameCorrelationStrategy class for username-based event correlation
|
|
38
|
+
* @extends EventEmitter
|
|
39
|
+
*/
|
|
40
|
+
class UsernameCorrelationStrategy extends EventEmitter {
|
|
41
|
+
/**
|
|
42
|
+
* Create a UsernameCorrelationStrategy
|
|
43
|
+
*
|
|
44
|
+
* @param {Object} options - Strategy options
|
|
45
|
+
* @param {Function} [options.usernameExtractor] - Function to extract username from event
|
|
46
|
+
* Default: (event) => event.data?.player
|
|
47
|
+
* @param {boolean} [options.includeMetadata=true] - Include session metadata (start/end times)
|
|
48
|
+
* @param {boolean} [options.autoCleanup=true] - Auto-remove inactive sessions
|
|
49
|
+
*/
|
|
50
|
+
constructor(options = {}) {
|
|
51
|
+
super();
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Function to extract username from event
|
|
55
|
+
* @private
|
|
56
|
+
* @type {Function}
|
|
57
|
+
*/
|
|
58
|
+
this._usernameExtractor = options.usernameExtractor || ((event) => event.data?.player);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Whether to include session metadata
|
|
62
|
+
* @private
|
|
63
|
+
* @type {boolean}
|
|
64
|
+
*/
|
|
65
|
+
this._includeMetadata = options.includeMetadata !== false;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Whether to auto-remove inactive sessions
|
|
69
|
+
* @private
|
|
70
|
+
* @type {boolean}
|
|
71
|
+
*/
|
|
72
|
+
this._autoCleanup = options.autoCleanup !== false;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Map of active player sessions
|
|
76
|
+
* @private
|
|
77
|
+
* @type {Map<string, Object>}
|
|
78
|
+
*/
|
|
79
|
+
this._sessions = new Map();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Correlate an event by username
|
|
84
|
+
*
|
|
85
|
+
* @param {Object} event - Parsed event object
|
|
86
|
+
* @returns {Object|null} - Session object with username, events, session metadata, or null if no username
|
|
87
|
+
*/
|
|
88
|
+
correlate(event) {
|
|
89
|
+
if (!event) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const username = this._usernameExtractor(event);
|
|
94
|
+
if (!username) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const now = Date.now();
|
|
99
|
+
|
|
100
|
+
if (!this._sessions.has(username)) {
|
|
101
|
+
this._sessions.set(username, {
|
|
102
|
+
username,
|
|
103
|
+
events: [],
|
|
104
|
+
sessionStart: this._includeMetadata ? now : undefined,
|
|
105
|
+
sessionEnd: undefined,
|
|
106
|
+
isActive: true
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const session = this._sessions.get(username);
|
|
111
|
+
session.events.push(event);
|
|
112
|
+
|
|
113
|
+
// Mark session as inactive on leave event
|
|
114
|
+
if (event.type === 'entity.leave') {
|
|
115
|
+
session.isActive = false;
|
|
116
|
+
if (this._includeMetadata) {
|
|
117
|
+
session.sessionEnd = now;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Auto-cleanup inactive sessions if enabled
|
|
121
|
+
if (this._autoCleanup) {
|
|
122
|
+
this._sessions.delete(username);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Emit session update event
|
|
127
|
+
this.emit('session', session);
|
|
128
|
+
|
|
129
|
+
return session;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get all active sessions
|
|
134
|
+
*
|
|
135
|
+
* @returns {Array<Object>} - Array of session objects
|
|
136
|
+
*/
|
|
137
|
+
getActiveCorrelations() {
|
|
138
|
+
return Array.from(this._sessions.values());
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get session by username
|
|
143
|
+
*
|
|
144
|
+
* @param {string} username - Username to look up
|
|
145
|
+
* @returns {Object|undefined} - Session object or undefined
|
|
146
|
+
*/
|
|
147
|
+
getSession(username) {
|
|
148
|
+
return this._sessions.get(username);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Check if a player has an active session
|
|
153
|
+
*
|
|
154
|
+
* @param {string} username - Username to check
|
|
155
|
+
* @returns {boolean} - True if player has an active session
|
|
156
|
+
*/
|
|
157
|
+
hasActiveSession(username) {
|
|
158
|
+
const session = this._sessions.get(username);
|
|
159
|
+
return !!(session && session.isActive);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get all currently online players
|
|
164
|
+
*
|
|
165
|
+
* @returns {Array<string>} - Array of usernames with active sessions
|
|
166
|
+
*/
|
|
167
|
+
getOnlinePlayers() {
|
|
168
|
+
return Array.from(this._sessions.values())
|
|
169
|
+
.filter(session => session.isActive)
|
|
170
|
+
.map(session => session.username);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Reset all session state
|
|
175
|
+
*
|
|
176
|
+
* @returns {void}
|
|
177
|
+
*/
|
|
178
|
+
reset() {
|
|
179
|
+
this._sessions.clear();
|
|
180
|
+
this.emit('reset');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* End a specific session manually
|
|
185
|
+
*
|
|
186
|
+
* @param {string} username - Username to end session for
|
|
187
|
+
* @returns {boolean} - True if session was ended, false if not found
|
|
188
|
+
*/
|
|
189
|
+
endSession(username) {
|
|
190
|
+
const session = this._sessions.get(username);
|
|
191
|
+
if (!session) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
session.isActive = false;
|
|
196
|
+
if (this._includeMetadata) {
|
|
197
|
+
session.sessionEnd = Date.now();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Auto-cleanup inactive sessions if enabled
|
|
201
|
+
if (this._autoCleanup) {
|
|
202
|
+
this._sessions.delete(username);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
this.emit('sessionEnd', session);
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get session statistics
|
|
211
|
+
*
|
|
212
|
+
* @returns {Object} - Statistics object with total, active, inactive counts
|
|
213
|
+
*/
|
|
214
|
+
getStatistics() {
|
|
215
|
+
const sessions = Array.from(this._sessions.values());
|
|
216
|
+
return {
|
|
217
|
+
total: sessions.length,
|
|
218
|
+
active: sessions.filter(s => s.isActive).length,
|
|
219
|
+
inactive: sessions.filter(s => !s.isActive).length
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get the number of active sessions
|
|
225
|
+
*
|
|
226
|
+
* @type {number}
|
|
227
|
+
*/
|
|
228
|
+
get size() {
|
|
229
|
+
return this._sessions.size;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
module.exports = { UsernameCorrelationStrategy };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Correlation Strategies
|
|
3
|
+
*
|
|
4
|
+
* Concrete implementations of CorrelationStrategy for various correlation patterns.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { TagCorrelationStrategy } = require('./TagCorrelationStrategy.js');
|
|
8
|
+
const { UsernameCorrelationStrategy } = require('./UsernameCorrelationStrategy.js');
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
TagCorrelationStrategy,
|
|
12
|
+
UsernameCorrelationStrategy
|
|
13
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Monitoring Module
|
|
3
|
+
*
|
|
4
|
+
* Provides continuous log monitoring with event processing and correlation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { CircularBuffer } = require('./CircularBuffer.js');
|
|
8
|
+
const { LogMonitor } = require('./LogMonitor.js');
|
|
9
|
+
const { TagCorrelationStrategy, UsernameCorrelationStrategy } = require('./correlations/index.js');
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
CircularBuffer,
|
|
13
|
+
LogMonitor,
|
|
14
|
+
TagCorrelationStrategy,
|
|
15
|
+
UsernameCorrelationStrategy
|
|
16
|
+
};
|