Skip to content

Commit ff71865

Browse files
authored
chore: Add guardrail for OTEL bridge (#3283)
1 parent 8b85342 commit ff71865

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

index.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ logger.info(
2626
pkgJSON.version,
2727
process.version
2828
)
29+
const path = require('node:path')
30+
const Module = require('node:module')
31+
const otelPackages = Object.keys(pkgJSON.dependencies).filter(d => d.startsWith('@opentelemetry'))
32+
const otelRequire = Module.createRequire(path.join(__dirname, __filename))
2933

3034
if (require.cache.__NR_cache) {
3135
logger.warn(
@@ -48,6 +52,7 @@ function initApi({ agent }) {
4852
return api
4953
}
5054

55+
// eslint-disable-next-line sonarjs/cognitive-complexity
5156
function initialize() {
5257
logger.debug('Loading agent from %s', __dirname)
5358
let agent = null
@@ -97,6 +102,10 @@ function initialize() {
97102
logger.warn(
98103
'New Relic for Node.js in worker_threads is not officially supported. Not starting! To bypass this, set `config.worker_threads.enabled` to true in configuration.'
99104
)
105+
} else if (config.opentelemetry_bridge.enabled === true && otelBridgeAvailable() === false) {
106+
logger.warn(
107+
'OpenTelemetry bridge enabled, but packages are missing. Not starting!'
108+
)
100109
} else {
101110
if (!isMainThread && config.worker_threads.enabled) {
102111
logger.warn(
@@ -278,3 +287,16 @@ function recordDisabledPackages(agent) {
278287
}
279288
}
280289
}
290+
291+
function otelBridgeAvailable() {
292+
for (const p of otelPackages) {
293+
try {
294+
otelRequire.resolve(p)
295+
} catch (error) {
296+
if (error.code === 'ERR_MODULE_NOT_FOUND') {
297+
return false
298+
}
299+
}
300+
}
301+
return true
302+
}

test/unit/index.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ test('index tests', async (t) => {
184184
logging: {},
185185
feature_flag: { flag_1: true, flag_2: false },
186186
security: { agent: { enabled: false } },
187-
worker_threads: { enabled: false }
187+
worker_threads: { enabled: false },
188+
opentelemetry_bridge: { enabled: false }
188189
}
189190
const configMock = {
190191
getOrCreateInstance: sandbox.stub().returns(mockConfig)

test/unit/otel-bridge.test.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2025 New Relic Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
'use strict'
7+
8+
// The purpose of this test is to verify that the agent will refuse to start
9+
// when any required Open Telemetry packages are not available and the bridge
10+
// is supposed to be enabled. The idea being, we can remove the OTEL packages
11+
// and start the agent with the bridge disabled in order to trim the size of
12+
// AWS Lambda Layers.
13+
14+
const test = require('node:test')
15+
const assert = require('node:assert')
16+
const Module = require('node:module')
17+
const proxyquire = require('proxyquire')
18+
19+
test('logs warning when missing otel packages', () => {
20+
process.env.NEW_RELIC_OPENTELEMETRY_BRIDGE_ENABLED = true
21+
22+
require.resolve = function resolve (...args) {
23+
if (args[0].startsWith('@opentelemetry') === true) {
24+
const error = Error('boom')
25+
error.code = 'ERR_MODULE_NOT_FOUND'
26+
throw error
27+
}
28+
return require.resolve.apply(require, args)
29+
}
30+
Module.createRequire = function () {
31+
return require
32+
}
33+
34+
const logs = []
35+
const agent = proxyquire('../../index.js', {
36+
'./lib/logger': {
37+
info() {},
38+
debug() {},
39+
warn(...args) {
40+
logs.push(args)
41+
}
42+
}
43+
})
44+
assert.ok(agent)
45+
agent.shutdown()
46+
assert.deepEqual(logs, [['OpenTelemetry bridge enabled, but packages are missing. Not starting!']])
47+
})

0 commit comments

Comments
 (0)