Add InfluxDB v3 unit tests and fix missing user events handling

Co-authored-by: mountaindude <1029262+mountaindude@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-09-24 20:40:09 +00:00
committed by Göran Sander
parent cedb89a1fd
commit a22e699870
2 changed files with 192 additions and 0 deletions

View File

@@ -232,6 +232,116 @@ describe('post-to-influxdb', () => {
);
});
test('should store log events to InfluxDB (InfluxDB v3)', async () => {
// Setup
globals.config.get = jest.fn((key) => {
if (key === 'Butler-SOS.influxdbConfig.version') return 3;
if (key === 'Butler-SOS.qlikSenseEvents.eventCount.influxdb.measurementName') {
return 'events_log';
}
if (key === 'Butler-SOS.influxdbConfig.v3Config.org') return 'test-org';
if (key === 'Butler-SOS.influxdbConfig.v3Config.database') return 'test-database';
return undefined;
});
const mockLogEvents = [
{
source: 'test-source',
host: 'test-host',
subsystem: 'test-subsystem',
counter: 5,
timestamp: '2023-01-01T00:00:00.000Z',
message: 'test message',
appName: 'test-app',
appId: 'test-app-id',
executionId: 'test-exec',
command: 'test-cmd',
resultCode: '200',
origin: 'test-origin',
context: 'test-context',
sessionId: 'test-session',
rawEvent: 'test-raw'
},
];
globals.udpEvents = {
getLogEvents: jest.fn().mockResolvedValue(mockLogEvents),
getUserEvents: jest.fn().mockResolvedValue([]),
};
globals.options = { instanceTag: 'test-instance' };
// Mock v3 writeApi
globals.influx.getWriteApi = jest.fn().mockReturnValue({
writePoint: jest.fn(),
});
// Execute
await influxdb.storeEventCountInfluxDB();
// Verify
expect(globals.influx.getWriteApi).toHaveBeenCalled();
// The writeApi mock's writePoint should be called
const writeApi = globals.influx.getWriteApi.mock.results[0].value;
expect(writeApi.writePoint).toHaveBeenCalled();
expect(globals.logger.verbose).toHaveBeenCalledWith(
expect.stringContaining(
'EVENT COUNT INFLUXDB: Sent Butler SOS event count data to InfluxDB'
)
);
});
test('should store user events to InfluxDB (InfluxDB v3)', async () => {
// Setup
globals.config.get = jest.fn((key) => {
if (key === 'Butler-SOS.influxdbConfig.version') return 3;
if (key === 'Butler-SOS.qlikSenseEvents.eventCount.influxdb.measurementName') {
return 'events_user';
}
if (key === 'Butler-SOS.influxdbConfig.v3Config.org') return 'test-org';
if (key === 'Butler-SOS.influxdbConfig.v3Config.database') return 'test-database';
return undefined;
});
const mockUserEvents = [
{
source: 'test-source',
host: 'test-host',
subsystem: 'test-subsystem',
counter: 3,
timestamp: '2023-01-01T00:00:00.000Z',
message: 'test message',
appName: 'test-app',
appId: 'test-app-id',
executionId: 'test-exec',
command: 'test-cmd',
resultCode: '200',
origin: 'test-origin',
context: 'test-context',
sessionId: 'test-session',
rawEvent: 'test-raw'
},
];
globals.udpEvents = {
getLogEvents: jest.fn().mockResolvedValue([]),
getUserEvents: jest.fn().mockResolvedValue(mockUserEvents),
};
globals.options = { instanceTag: 'test-instance' };
// Mock v3 writeApi
globals.influx.getWriteApi = jest.fn().mockReturnValue({
writePoint: jest.fn(),
});
// Execute
await influxdb.storeEventCountInfluxDB();
// Verify
expect(globals.influx.getWriteApi).toHaveBeenCalled();
// The writeApi mock's writePoint should be called
const writeApi = globals.influx.getWriteApi.mock.results[0].value;
expect(writeApi.writePoint).toHaveBeenCalled();
expect(globals.logger.verbose).toHaveBeenCalledWith(
expect.stringContaining(
'EVENT COUNT INFLUXDB: Sent Butler SOS event count data to InfluxDB'
)
);
});
test('should handle errors gracefully (InfluxDB v1)', async () => {
// Setup
globals.config.get = jest.fn((key) => {
@@ -601,6 +711,42 @@ describe('post-to-influxdb', () => {
expect(globals.influxWriteApi[0].writeAPI.writePoints).toHaveBeenCalled();
});
test('should post health metrics to InfluxDB v3', async () => {
globals.config.get = jest.fn((key) => {
if (key === 'Butler-SOS.influxdbConfig.version') return 3;
if (key === 'Butler-SOS.influxdbConfig.includeFields.activeDocs') return false;
if (key === 'Butler-SOS.influxdbConfig.includeFields.loadedDocs') return false;
if (key === 'Butler-SOS.influxdbConfig.includeFields.inMemoryDocs') return false;
if (key === 'Butler-SOS.appNames.enableAppNameExtract') return false;
return undefined;
});
globals.influxWriteApi = [
{
serverName: 'testserver',
writeAPI: {
writePoints: jest.fn(),
},
},
];
const serverName = 'testserver';
const host = 'testhost';
const serverTags = { host: 'testhost', server_name: 'testserver' };
const healthBody = {
version: '1.0.0',
started: '20220801T121212.000Z',
apps: { active_docs: [], loaded_docs: [], in_memory_docs: [], calls: 100, selections: 50 },
cache: { added: 0, hits: 10, lookups: 15, replaced: 2, bytes_added: 1000 },
cpu: { total: 25 },
mem: { committed: 1000, allocated: 800, free: 200 },
session: { active: 5, total: 10 },
users: { active: 3, total: 8 },
};
await influxdb.postHealthMetricsToInfluxdb(serverName, host, healthBody, serverTags);
expect(globals.influxWriteApi[0].writeAPI.writePoints).toHaveBeenCalled();
});
});
describe('postProxySessionsToInfluxdb', () => {

View File

@@ -2180,6 +2180,52 @@ export async function storeEventCountInfluxDB() {
globals.logger.debug(`EVENT COUNT INFLUXDB: Wrote data to InfluxDB v3`);
}
// Loop through data in user events and create datapoints.
for (const event of userEvents) {
const tags = {
butler_sos_instance: globals.options.instanceTag,
event_type: 'user',
source: event.source,
host: event.host,
subsystem: event.subsystem,
};
// Add static tags defined in config file, if any
if (
globals.config.has('Butler-SOS.qlikSenseEvents.eventCount.influxdb.tags') &&
Array.isArray(
globals.config.get('Butler-SOS.qlikSenseEvents.eventCount.influxdb.tags')
)
) {
const configTags = globals.config.get(
'Butler-SOS.qlikSenseEvents.eventCount.influxdb.tags'
);
configTags.forEach((tag) => {
tags[tag.name] = tag.value;
});
}
const point = new Point(
globals.config.get(
'Butler-SOS.qlikSenseEvents.eventCount.influxdb.measurementName'
)
)
.tag('event_type', 'user')
.tag('source', event.source)
.tag('host', event.host)
.tag('subsystem', event.subsystem)
.intField('counter', event.counter);
// Add tags to point
Object.keys(tags).forEach((key) => {
point.tag(key, tags[key]);
});
const res = await writeApi.writePoint(point);
globals.logger.debug(`EVENT COUNT INFLUXDB: Wrote user event data to InfluxDB v3`);
}
globals.logger.verbose(
'EVENT COUNT INFLUXDB: Sent Butler SOS event count data to InfluxDB'
);