Skip to content

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

Open
@davidalpert

Description

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

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