Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 0 additions & 54 deletions packages/collector/src/agent/log.js

This file was deleted.

21 changes: 17 additions & 4 deletions packages/collector/src/agent/loggerToAgentStream.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@

'use strict';

const log = require('./log');

const pidStore = require('../pidStore/internalPidStore');

/** @type {NodeJS.WritableStream} */
/** @type {import('../agentConnection')} */
let downstreamConnection;

/** @type {NodeJS.WritableStream & {
* setDownstreamConnection: (downstreamConnection: import('../agentConnection')) => void
* }} */
module.exports = {
/**
* @param {*} record
Expand All @@ -30,7 +33,17 @@ module.exports = {
stack = record.err.stack;
}

log(logLevel, message, stack);
// CASE: It could be that the preinit functionality calls the logger before the agent connection is properly set up.
if (downstreamConnection) {
downstreamConnection.sendLogToAgent(logLevel, message, stack);
}
},

/**
* @param {import('../agentConnection')} _downstreamConnection
*/
setDownstreamConnection: _downstreamConnection => {
downstreamConnection = _downstreamConnection;
}
};

Expand Down
46 changes: 46 additions & 0 deletions packages/collector/src/agentConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,52 @@ exports.checkWhetherAgentIsReadyToAcceptData = function checkWhetherAgentIsReady
checkWhetherResponseForPathIsOkay(`/com.instana.plugin.nodejs.${pidStore.pid}`, cb);
};

/**
* @param {*} logLevel
* @param {*} message
* @param {*} stackTrace
*/
exports.sendLogToAgent = function sendLogToAgent(logLevel, message, stackTrace) {
/** @type {{m: string, st?: string}} */
const payloadObject = {
m: message.trim()
};

if (stackTrace) {
payloadObject.st = stackTrace.trim();
}

const payload = Buffer.from(JSON.stringify(payloadObject), 'utf8');

const req = http.request(
{
host: agentOpts.host,
port: agentOpts.port,
path: '/com.instana.agent.logger',
method: 'POST',
agent: http.agent,
headers: {
'Content-Type': 'application/json; charset=UTF-8',
'Content-Length': payload.length,
'x-log-level': logLevel
}
},
res => {
res.resume();
}
);

function swallow() {
// swallow all errors
}

req.setTimeout(agentOpts.requestTimeout, swallow);
req.on('error', swallow);

req.write(payload);
req.end();
};

/**
* @param {string} path
* @param {(...args: *) => *} cb
Expand Down
2 changes: 2 additions & 0 deletions packages/collector/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ function init(userConfig = {}) {
const announceCycle = require('./announceCycle');
const metrics = require('./metrics');

log.setDownstreamConnection(agentConnection);

pidStore.init(config);
agentOpts.init(config);
announceCycle.init(config, pidStore);
Expand Down
8 changes: 8 additions & 0 deletions packages/collector/src/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ exports.init = function init(userConfig = {}) {

exports.getLogger = () => instanaLogger;

/**
*
* @param {import('./agentConnection')} downstreamConnection
*/
exports.setDownstreamConnection = downstreamConnection => {
loggerToAgentStream.setDownstreamConnection(downstreamConnection);
};

/**
* @param {import('@instana/core/src/core').GenericLogger | *} _logger
* @returns {boolean}
Expand Down
11 changes: 11 additions & 0 deletions packages/collector/test/apps/agentStub.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const ignoreEndpoints = process.env.IGNORE_ENDPOINTS && JSON.parse(process.env.I
const disable = process.env.AGENT_DISABLE_TRACING && JSON.parse(process.env.AGENT_DISABLE_TRACING);

const uuids = {};
const agentLogs = [];
let discoveries = {};
let rejectAnnounceAttempts = 0;
let requests = {};
Expand Down Expand Up @@ -136,6 +137,16 @@ app.head(
})
);

app.post('/com.instana.agent.logger', (req, res) => {
logger.info('Received log message from agent: %j', req.body);
agentLogs.push(req.body);
res.sendStatus(200);
});

app.get('/agent/logs', (req, res) => {
res.json(agentLogs);
});

app.post(
'/com.instana.plugin.nodejs.:pid',
checkExistenceOfKnownPid(function handleEntityData(req, res) {
Expand Down
9 changes: 9 additions & 0 deletions packages/collector/test/apps/agentStubControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,15 @@ class AgentStubControls {
});
}

getAgentLogs() {
return fetch(`http://127.0.0.1:${this.agentPort}/agent/logs`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}).then(response => response.json());
}

async reset() {
// eslint-disable-next-line no-console
console.log(`[AgentStubControls] reset ${this.agentPort}`);
Expand Down
44 changes: 44 additions & 0 deletions packages/collector/test/tracing/misc/agent-logs/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* (c) Copyright IBM Corp. 20215
*/

'use strict';

// NOTE: c8 bug https://github.com/bcoe/c8/issues/166
process.on('SIGTERM', () => {
process.disconnect();
process.exit(0);
});

const agentPort = process.env.INSTANA_AGENT_PORT;

require('../../../..')({
// NOTE: The test env mutes all logs by default. No logs, no agent logs.
level: 'info'
});

const express = require('express');
const port = require('../../../test_util/app-port')();
const app = express();

const logPrefix = `Agent Logs App (${process.pid}):\t`;

app.get('/', (req, res) => {
res.send();
});

app.get('/trace', async (req, res) => {
await fetch(`http://127.0.0.1:${agentPort}`);
res.send();
});

app.listen(port, () => {
log(`Listening on port: ${port}`);
});

function log() {
/* eslint-disable no-console */
const args = Array.prototype.slice.call(arguments);
args[0] = logPrefix + args[0];
console.log.apply(console, args);
}
55 changes: 55 additions & 0 deletions packages/collector/test/tracing/misc/agent-logs/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* (c) Copyright IBM Corp. 2025
*/

'use strict';

const { expect } = require('chai');
const supportedVersion = require('@instana/core').tracing.supportedVersion;
const config = require('../../../../../core/test/config');
const testUtils = require('../../../../../core/test/test_util');
const ProcessControls = require('../../../test_util/ProcessControls');
const globalAgent = require('../../../globalAgent');
const agentControls = globalAgent.instance;

const mochaSuiteFn = supportedVersion(process.versions.node) ? describe : describe.skip;

mochaSuiteFn('tracing/agent logs', function () {
this.timeout(config.getTestTimeout());
globalAgent.setUpCleanUpHooks();

describe('Ensure agent logs are transmitted', function () {
let controls;

before(async () => {
controls = new ProcessControls({
dirname: __dirname,
useGlobalAgent: true
});

await controls.startAndWaitForAgentConnection();
});

beforeEach(async () => {
await agentControls.clearReceivedTraceData();
});

after(async () => {
await controls.stop();
});

it('expect agent logs data', async () => {
await controls.sendRequest({
path: '/trace'
});

await testUtils.retry(async () => {
const spans = await agentControls.getSpans();
const agentLogs = await agentControls.getAgentLogs();

expect(spans.length).to.equal(2);
expect(agentLogs.length).to.equal(9);
});
});
});
});