Skip to content

Getting TraceID from an OpenTracing DatadogSpanContext can throw "Cannot read properties of undefined (reading 'toString') #4987

Open
@davidalpert

Description

@davidalpert

Calling this DatadogSpanContext.toTraceId() method on what appears to be a valid span can sometimes error out with an undefined inner this._traceId value:

toTraceId (get128bitId = false) {
if (get128bitId) {
return this._traceId.toBuffer().length <= 8 && this._trace.tags[TRACE_ID_128]
? this._trace.tags[TRACE_ID_128] + this._traceId.toString(16).padStart(16, '0')
: this._traceId.toString(16).padStart(32, '0')
}
return this._traceId.toString(10)
}

Suggested Solution

  • While I am not sure what might cause this scenario, a quick fix would be to make the dot property access of this._traceId a bit more defensive:

     toTraceId (get128bitId = false) {
        if (this._traceId && get128bitId) {
          return this._traceId.toBuffer().length <= 8 && this._trace.tags[TRACE_ID_128]
            ? this._trace.tags[TRACE_ID_128] + this._traceId.toString(16).padStart(16, '0')
            : this._traceId.toString(16).padStart(32, '0')
        }
        return this._traceId?.toString(10)
      }
    

Replication Steps

  • Using:

        "dd-trace": "5.25.0",
    
  • Initialize the tracer on startup:

    import tracer from 'dd-trace';
    import { version } from '../../package.json';
    import { buildVars } from '#root/.build/buildVars';
    
    tracer.init({
      service: process.env.DD_SERVICE || 'my-fe-app',
      version: version ? `${version}-${buildVars.GIT_SHA}` : '0.0.0',
      tags: {
        pid: process.pid,
      },
      runtimeMetrics: true,
      logInjection: true,
    });
    
  • Try to defensively get the active span's traceID at runtime

    import tracer from 'dd-trace';
    
    ...
    
        const span = tracer.scope().active();
        const traceID = span?.context()?.toTraceId() ?? 'n/a';
    
    ...
    

Expected result

  • traceID is either a valid Trace ID from the current span or undefined in which case we default to 'n/a/ based on the code above

Actual result

  • We regularly encounter an error whereby we seem to have a defined span (i.e. not null or undefined) with an empty or missing DatadogSpanContext._traceID property such that when we call toTraceId() on it we get the following error:

    .../my_app/node_modules/dd-trace/packages/dd-trace/src/opentracing/span_context.js:39
         return this._traceId.toString(10)
                                          ^
    TypeError: Cannot read properties of undefined (reading 'toString')
         at DatadogSpanContext.toTraceId (.../my_app/packages/dd-trace/src/opentracing/span_context.js:39:26)
    

Unit Tests

  • Here is a failing test we can add to packages/dd-trace/test/opentracing/span_context.spec.js to demonstrate the issue

    'use strict'
    
    require('../setup/tap')
    
    const { expect } = require('chai')
    const id = require('../../src/id')
    
    describe('SpanContext', () => {
      let SpanContext
      let TraceState
    
      beforeEach(() => {
        SpanContext = require('../../src/opentracing/span_context')
        TraceState = require('../../src/opentracing/propagation/tracestate')
      })
     
      ...
      describe('toTraceparent()', () => {
      ...
    
        it('should allow nullsafe access to trace ID', () => {
          const spanContext = new SpanContext({
            traceId: undefined,
            spanId: id('456', 16)
          })
    
          spanContext._trace.tags['_dd.p.tid'] = null
    
          expect(spanContext.toTraceId()).to.equal(undefined)
        })
      })
    })
    

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions