Skip to content

Commit acef2c0

Browse files
authored
refactor: removed agent/log.js and move the fn to agent connection (#2012)
From #2010
1 parent 7bf0c36 commit acef2c0

File tree

9 files changed

+192
-58
lines changed

9 files changed

+192
-58
lines changed

packages/collector/src/agent/log.js

Lines changed: 0 additions & 54 deletions
This file was deleted.

packages/collector/src/agent/loggerToAgentStream.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55

66
'use strict';
77

8-
const log = require('./log');
9-
108
const pidStore = require('../pidStore/internalPidStore');
119

12-
/** @type {NodeJS.WritableStream} */
10+
/** @type {import('../agentConnection')} */
11+
let downstreamConnection;
12+
13+
/** @type {NodeJS.WritableStream & {
14+
* setDownstreamConnection: (downstreamConnection: import('../agentConnection')) => void
15+
* }} */
1316
module.exports = {
1417
/**
1518
* @param {*} record
@@ -30,7 +33,17 @@ module.exports = {
3033
stack = record.err.stack;
3134
}
3235

33-
log(logLevel, message, stack);
36+
// CASE: It could be that the preinit functionality calls the logger before the agent connection is properly set up.
37+
if (downstreamConnection) {
38+
downstreamConnection.sendLogToAgent(logLevel, message, stack);
39+
}
40+
},
41+
42+
/**
43+
* @param {import('../agentConnection')} _downstreamConnection
44+
*/
45+
setDownstreamConnection: _downstreamConnection => {
46+
downstreamConnection = _downstreamConnection;
3447
}
3548
};
3649

packages/collector/src/agentConnection.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,52 @@ exports.checkWhetherAgentIsReadyToAcceptData = function checkWhetherAgentIsReady
216216
checkWhetherResponseForPathIsOkay(`/com.instana.plugin.nodejs.${pidStore.pid}`, cb);
217217
};
218218

219+
/**
220+
* @param {*} logLevel
221+
* @param {*} message
222+
* @param {*} stackTrace
223+
*/
224+
exports.sendLogToAgent = function sendLogToAgent(logLevel, message, stackTrace) {
225+
/** @type {{m: string, st?: string}} */
226+
const payloadObject = {
227+
m: message.trim()
228+
};
229+
230+
if (stackTrace) {
231+
payloadObject.st = stackTrace.trim();
232+
}
233+
234+
const payload = Buffer.from(JSON.stringify(payloadObject), 'utf8');
235+
236+
const req = http.request(
237+
{
238+
host: agentOpts.host,
239+
port: agentOpts.port,
240+
path: '/com.instana.agent.logger',
241+
method: 'POST',
242+
agent: http.agent,
243+
headers: {
244+
'Content-Type': 'application/json; charset=UTF-8',
245+
'Content-Length': payload.length,
246+
'x-log-level': logLevel
247+
}
248+
},
249+
res => {
250+
res.resume();
251+
}
252+
);
253+
254+
function swallow() {
255+
// swallow all errors
256+
}
257+
258+
req.setTimeout(agentOpts.requestTimeout, swallow);
259+
req.on('error', swallow);
260+
261+
req.write(payload);
262+
req.end();
263+
};
264+
219265
/**
220266
* @param {string} path
221267
* @param {(...args: *) => *} cb

packages/collector/src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ function init(userConfig = {}) {
113113
const announceCycle = require('./announceCycle');
114114
const metrics = require('./metrics');
115115

116+
log.setDownstreamConnection(agentConnection);
117+
116118
pidStore.init(config);
117119
agentOpts.init(config);
118120
announceCycle.init(config, pidStore);

packages/collector/src/logger.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ exports.init = function init(userConfig = {}) {
158158

159159
exports.getLogger = () => instanaLogger;
160160

161+
/**
162+
*
163+
* @param {import('./agentConnection')} downstreamConnection
164+
*/
165+
exports.setDownstreamConnection = downstreamConnection => {
166+
loggerToAgentStream.setDownstreamConnection(downstreamConnection);
167+
};
168+
161169
/**
162170
* @param {import('@instana/core/src/core').GenericLogger | *} _logger
163171
* @returns {boolean}

packages/collector/test/apps/agentStub.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const ignoreEndpoints = process.env.IGNORE_ENDPOINTS && JSON.parse(process.env.I
4646
const disable = process.env.AGENT_DISABLE_TRACING && JSON.parse(process.env.AGENT_DISABLE_TRACING);
4747

4848
const uuids = {};
49+
const agentLogs = [];
4950
let discoveries = {};
5051
let rejectAnnounceAttempts = 0;
5152
let requests = {};
@@ -136,6 +137,16 @@ app.head(
136137
})
137138
);
138139

140+
app.post('/com.instana.agent.logger', (req, res) => {
141+
logger.info('Received log message from agent: %j', req.body);
142+
agentLogs.push(req.body);
143+
res.sendStatus(200);
144+
});
145+
146+
app.get('/agent/logs', (req, res) => {
147+
res.json(agentLogs);
148+
});
149+
139150
app.post(
140151
'/com.instana.plugin.nodejs.:pid',
141152
checkExistenceOfKnownPid(function handleEntityData(req, res) {

packages/collector/test/apps/agentStubControls.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,15 @@ class AgentStubControls {
175175
});
176176
}
177177

178+
getAgentLogs() {
179+
return fetch(`http://127.0.0.1:${this.agentPort}/agent/logs`, {
180+
method: 'GET',
181+
headers: {
182+
'Content-Type': 'application/json'
183+
}
184+
}).then(response => response.json());
185+
}
186+
178187
async reset() {
179188
// eslint-disable-next-line no-console
180189
console.log(`[AgentStubControls] reset ${this.agentPort}`);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* (c) Copyright IBM Corp. 20215
3+
*/
4+
5+
'use strict';
6+
7+
// NOTE: c8 bug https://github.com/bcoe/c8/issues/166
8+
process.on('SIGTERM', () => {
9+
process.disconnect();
10+
process.exit(0);
11+
});
12+
13+
const agentPort = process.env.INSTANA_AGENT_PORT;
14+
15+
require('../../../..')({
16+
// NOTE: The test env mutes all logs by default. No logs, no agent logs.
17+
level: 'info'
18+
});
19+
20+
const express = require('express');
21+
const port = require('../../../test_util/app-port')();
22+
const app = express();
23+
24+
const logPrefix = `Agent Logs App (${process.pid}):\t`;
25+
26+
app.get('/', (req, res) => {
27+
res.send();
28+
});
29+
30+
app.get('/trace', async (req, res) => {
31+
await fetch(`http://127.0.0.1:${agentPort}`);
32+
res.send();
33+
});
34+
35+
app.listen(port, () => {
36+
log(`Listening on port: ${port}`);
37+
});
38+
39+
function log() {
40+
/* eslint-disable no-console */
41+
const args = Array.prototype.slice.call(arguments);
42+
args[0] = logPrefix + args[0];
43+
console.log.apply(console, args);
44+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* (c) Copyright IBM Corp. 2025
3+
*/
4+
5+
'use strict';
6+
7+
const { expect } = require('chai');
8+
const supportedVersion = require('@instana/core').tracing.supportedVersion;
9+
const config = require('../../../../../core/test/config');
10+
const testUtils = require('../../../../../core/test/test_util');
11+
const ProcessControls = require('../../../test_util/ProcessControls');
12+
const globalAgent = require('../../../globalAgent');
13+
const agentControls = globalAgent.instance;
14+
15+
const mochaSuiteFn = supportedVersion(process.versions.node) ? describe : describe.skip;
16+
17+
mochaSuiteFn('tracing/agent logs', function () {
18+
this.timeout(config.getTestTimeout());
19+
globalAgent.setUpCleanUpHooks();
20+
21+
describe('Ensure agent logs are transmitted', function () {
22+
let controls;
23+
24+
before(async () => {
25+
controls = new ProcessControls({
26+
dirname: __dirname,
27+
useGlobalAgent: true
28+
});
29+
30+
await controls.startAndWaitForAgentConnection();
31+
});
32+
33+
beforeEach(async () => {
34+
await agentControls.clearReceivedTraceData();
35+
});
36+
37+
after(async () => {
38+
await controls.stop();
39+
});
40+
41+
it('expect agent logs data', async () => {
42+
await controls.sendRequest({
43+
path: '/trace'
44+
});
45+
46+
await testUtils.retry(async () => {
47+
const spans = await agentControls.getSpans();
48+
const agentLogs = await agentControls.getAgentLogs();
49+
50+
expect(spans.length).to.equal(2);
51+
expect(agentLogs.length).to.equal(9);
52+
});
53+
});
54+
});
55+
});

0 commit comments

Comments
 (0)