Skip to content

GraphQL UnifiedTrace does not generate RED metrics (missing set_measured() call) #5218

@fabn

Description

@fabn

Summary

The UnifiedTrace module for GraphQL does not call Contrib::Analytics.set_measured(span) on the graphql.execute span, which prevents RED (Rate, Errors, Duration) metrics from being generated. This makes it impossible to use standard Datadog monitoring features like the Service Page operations list and trace.graphql.* metrics.

Expected Behavior

When using with_unified_tracer: true, the graphql.execute span should:

  1. Appear as a top-level operation in the Datadog Service Page
  2. Generate trace.graphql.execute.* metrics (hits, errors, duration)
  3. Be usable for monitors and SLOs based on these metrics

Actual Behavior

  • The graphql.execute span appears correctly in traces with proper resource names
  • However, it does not appear in the Service Page operations list
  • No trace.graphql.* metrics are generated
  • Cannot create monitors/SLOs based on GraphQL operation performance

Root Cause Analysis

Comparing UnifiedTrace with other integrations that correctly appear as top-level operations:

Sidekiq ServerTracer (source):

span.set_tag(
  Datadog::Tracing::Metadata::Ext::TAG_KIND,
  Datadog::Tracing::Metadata::Ext::SpanKind::TAG_CONSUMER
)

# Measure service stats
Contrib::Analytics.set_measured(span)  # ✅ Present

Rack Middleware (source):

request_span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_SERVER)

# Measure service stats
Contrib::Analytics.set_measured(request_span)  # ✅ Present

GraphQL UnifiedTrace (source):

# In execute_query method:
span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_SERVER)
# ❌ Missing: Contrib::Analytics.set_measured(span)

The comment on line 86-87 states:

# Ensure this span can be aggregated by in the Datadog App, and generates RED metrics.
span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_SERVER)

However, setting TAG_KIND = TAG_SERVER alone is not sufficient to generate RED metrics. The _dd.measured = 1 tag (set by set_measured()) is required.

Suggested Fix

In unified_trace.rb, add the set_measured() call in the execute_query method's before lambda:

def execute_query(*args, query:, **kwargs)
  trace(
    proc { super },
    'execute',
    operation_resource(query.selected_operation),
    lambda { |span|
      span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_SERVER)
      
      # Add this line to enable RED metrics generation
      Contrib::Analytics.set_measured(span)
      
      span.set_tag('graphql.source', query.query_string)
      # ... rest of the method
    },
    # ...
  )
end

Environment

  • dd-trace-rb version: 2.x (tested with latest)
  • Ruby version: 3.2.2
  • GraphQL version: 2.x
  • Configuration:
Datadog.configure do |c|
  c.tracing.instrument :graphql, with_unified_tracer: true
end

Additional Context

This issue is particularly impactful for applications where GraphQL is the primary API layer, as it prevents effective monitoring of API performance without falling back to the less feature-rich legacy tracer.

Contribution

I'm happy to submit a PR implementing the suggested fix if the proposed approach is confirmed to be correct.

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