Skip to content

Add flag evaluation metrics via OTel counter and OpenFeature Hook#11040

Draft
typotter wants to merge 3 commits intomasterfrom
typo/evaluations-logging
Draft

Add flag evaluation metrics via OTel counter and OpenFeature Hook#11040
typotter wants to merge 3 commits intomasterfrom
typo/evaluations-logging

Conversation

@typotter
Copy link
Copy Markdown
Contributor

@typotter typotter commented Apr 2, 2026

What Does This Do

Records a feature_flag.evaluations OTel counter metric on every flag evaluation via an OpenFeature finallyAfter hook. The hook captures all evaluation paths including type mismatches that occur above the provider level in the OpenFeature SDK pipeline.

Creates a dedicated SdkMeterProvider with an OtlpHttpMetricExporter that sends metrics directly to the DD Agent's OTLP endpoint (/v1/metrics). This avoids the agent's OTel class shading (io.opentelemetry.api.*datadog.trace.bootstrap.otel.api.*) which prevents using GlobalOpenTelemetry from the published dd-openfeature jar.

Metric attributes:

Attribute When present Value
feature_flag.key Always Flag key
feature_flag.result.variant Always Variant key (empty string if null)
feature_flag.result.reason Always Reason lowercased
error.type On error ErrorCode lowercased
feature_flag.result.allocation_key When present Allocation key from flag metadata

New files: FlagEvalMetrics.java, FlagEvalHook.java, FlagEvalMetricsTest.java, FlagEvalHookTest.java
Modified files: Provider.java (adds getProviderHooks()), ProviderTest.java, build.gradle.kts

Motivation

Evaluation metrics allow tracking how many times flags are evaluated, with which results, across sessions. This is the Java implementation of the evaluation logging spec (FFL-1942), matching the existing Python (dd-trace-py#17029) and Go (dd-trace-go#4489) implementations.

System tests: 11/17 pass. The 6 remaining failures are pre-existing DDEvaluator gaps (reason mapping, parse error codes) addressed in separate PRs (#11036, #10971).

References:

Additional Notes

  • OTel SDK dependencies (opentelemetry-sdk-metrics, opentelemetry-exporter-otlp) are compileOnly — applications must include them on the classpath for metrics to flow. Falls back to silent no-op when absent.
  • Export interval: 10s (matching Go SDK and EVALLOG.4 spec)
  • Endpoint resolution follows OTel spec: OTEL_EXPORTER_OTLP_METRICS_ENDPOINTOTEL_EXPORTER_OTLP_ENDPOINT + /v1/metricshttp://localhost:4318/v1/metrics

Contributor Checklist

  • Format the title according to the contribution guidelines
  • Assign the type: and (comp: or inst:) labels
  • Avoid using close, fix, or any linking keywords when referencing an issue

Jira ticket: FFL-1942

typotter added 3 commits April 1, 2026 20:29
Record a `feature_flag.evaluations` OTel counter on every flag evaluation
using an OpenFeature `finallyAfter` hook. The hook captures all evaluation
paths including type mismatches that occur above the provider level.

Attributes: feature_flag.key, feature_flag.result.variant,
feature_flag.result.reason, error.type (on error),
feature_flag.result.allocation_key (when present).

Counter is a no-op when DD_METRICS_OTEL_ENABLED is false or
opentelemetry-api is absent from the classpath.
Replace GlobalOpenTelemetry.getMeterProvider() with a dedicated
SdkMeterProvider + OtlpHttpMetricExporter that sends metrics
directly to the DD Agent's OTLP endpoint (default :4318/v1/metrics).

This avoids the agent's OTel class shading issue where the agent
relocates io.opentelemetry.api.* to datadog.trace.bootstrap.otel.api.*,
making GlobalOpenTelemetry calls from the dd-openfeature jar hit the
unshaded no-op provider instead of the agent's shim.

Requires opentelemetry-sdk-metrics and opentelemetry-exporter-otlp
on the application classpath. Falls back to no-op if absent.

System tests: 11/17 pass. 6 failures are pre-existing DDEvaluator
gaps (reason mapping, parse errors, type mismatch strictness).
- Add explicit null guard for details in FlagEvalHook.finallyAfter()
- Add OTEL_EXPORTER_OTLP_ENDPOINT generic env var fallback with
  /v1/metrics path appended (per OTel spec fallback chain)
- Add comments clarifying signal-specific vs generic endpoint behavior
@typotter typotter added type: feature request tag: ai generated Largely based on code generated by an AI or LLM comp: openfeature OpenFeature labels Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: openfeature OpenFeature tag: ai generated Largely based on code generated by an AI or LLM type: feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant