diff --git a/lib/otel/rules.js b/lib/otel/rules.js index 855435bfad..23f21bbc2c 100644 --- a/lib/otel/rules.js +++ b/lib/otel/rules.js @@ -75,15 +75,26 @@ class Rule { } get type() { - return this.#type + if (this.#type) { + return this.#type + } + return this.isServerRule ? 'server' : 'client' } - get isServerRule() { - return this.#spanKinds.includes(Rule.OTEL_SPAN_KIND_SERVER) + get isClientRule() { + return this.#spanKinds.includes(Rule.OTEL_SPAN_KIND_CLIENT) || this.isProducer } - get isClientRule() { - return this.#spanKinds.includes(Rule.OTEL_SPAN_KIND_CLIENT) + get isConsumer() { + return this.#spanKinds.includes('consumer') + } + + get isProducer() { + return this.#spanKinds.includes('producer') + } + + get isServerRule() { + return this.#spanKinds.includes(Rule.OTEL_SPAN_KIND_SERVER) || this.isConsumer } /** @@ -112,11 +123,23 @@ class Rule { class RulesEngine { #serverRules = new Map() + #fallbackServerRules = new Map() #clientRules = new Map() + #fallbackClientRules = new Map() constructor() { for (const inputRule of srcJson) { const rule = new Rule(inputRule) + + if (/fallback/i.test(rule.name) === true) { + if (rule.isServerRule === true) { + this.#fallbackServerRules.set(rule.name, rule) + } else if (rule.isClientRule === true) { + this.#fallbackClientRules.set(rule.name, rule) + } + continue + } + if (rule.isServerRule === true) { this.#serverRules.set(rule.name, rule) } else if (rule.isClientRule === true) { @@ -133,13 +156,20 @@ class RulesEngine { * * @returns {Rule|undefined} */ + // eslint-disable-next-line sonarjs/cognitive-complexity test(otelSpan) { let result - switch (otelSpan.kind) { + detector: switch (otelSpan.kind) { case SpanKind.SERVER: case SpanKind.CONSUMER: { for (const rule of this.#serverRules.values()) { + if (rule.matches(otelSpan) === true) { + result = rule + break detector + } + } + for (const rule of this.#fallbackServerRules.values()) { if (rule.matches(otelSpan) === true) { result = rule break @@ -151,6 +181,12 @@ class RulesEngine { case SpanKind.CLIENT: case SpanKind.PRODUCER: { for (const rule of this.#clientRules.values()) { + if (rule.matches(otelSpan) === true) { + result = rule + break detector + } + } + for (const rule of this.#fallbackClientRules.values()) { if (rule.matches(otelSpan) === true) { result = rule break diff --git a/test/unit/lib/otel/rules.test.js b/test/unit/lib/otel/rules.test.js index 6080acc8ee..80805f39a8 100644 --- a/test/unit/lib/otel/rules.test.js +++ b/test/unit/lib/otel/rules.test.js @@ -20,10 +20,10 @@ const spanContext = { spanId: '6e0c63257de34c92', traceFlags: TraceFlags.SAMPLED } +const parentId = '5c1c63257de34c67' test('engine returns correct matching rule', () => { const engine = new RulesEngine() - const parentId = '5c1c63257de34c67' const span = new Span(tracer, ROOT_CONTEXT, 'test-span', spanContext, SpanKind.SERVER, parentId) span.setAttribute('http.request.method', 'GET') span.end() @@ -32,3 +32,36 @@ test('engine returns correct matching rule', () => { assert.notEqual(rule, undefined) assert.equal(rule.name, 'OtelHttpServer1_23') }) + +test('consumer does not match fallback rule', () => { + const engine = new RulesEngine() + const span = new Span(tracer, ROOT_CONTEXT, 'test-span', spanContext, SpanKind.CONSUMER, parentId) + span.setAttribute('messaging.operation', 'create') + span.end() + + const rule = engine.test(span) + assert.notEqual(rule, undefined) + assert.equal(rule.name, 'OtelMessagingConsumer1_24') +}) + +test('fallback server rule is met', () => { + const engine = new RulesEngine() + const span = new Span(tracer, ROOT_CONTEXT, 'test-span', spanContext, SpanKind.SERVER, parentId) + span.setAttribute('foo.bar', 'baz') + span.end() + + const rule = engine.test(span) + assert.notEqual(rule, undefined) + assert.equal(rule.name, 'FallbackServer') +}) + +test('fallback client rule is met', () => { + const engine = new RulesEngine() + const span = new Span(tracer, ROOT_CONTEXT, 'test-span', spanContext, SpanKind.PRODUCER, parentId) + span.setAttribute('foo.bar', 'baz') + span.end() + + const rule = engine.test(span) + assert.notEqual(rule, undefined) + assert.equal(rule.name, 'FallbackClient') +})