Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generated using mix protox.generate with --namespace=OtelMetricExporter. All module names are preserved (e.g. OtelMetricExporter.Opentelemetry.Proto.Common.V1.AnyValue). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- otel_api.ex: Protobuf.encode_to_iodata -> Protox.encode! (returns {iodata, size})
- protocol.ex: Use atoms directly for severity numbers instead of SeverityNumber.value/1
- protocol.ex: Default event_name to "" instead of nil (protox validates string fields)
- metric_store.ex: Default unit to "" and description to "" when nil
- metric_store.ex: Default nil metric values to 0/0.0 instead of nil
- test files: Protobuf.decode -> Protox.decode!, Module.decode -> Module.decode!
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Minor version bump for protobuf -> protox migration. Public API unchanged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e5ca070e11
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| defp convert_value(nil, :int), do: {:as_int, 0} | ||
| defp convert_value(nil, :double), do: {:as_double, 0.0} |
There was a problem hiding this comment.
Skip nil measurements instead of coercing them to zero
If a Telemetry.Metrics.last_value/2 uses an optional measurement key or a measurement callback returns nil, handle_metric/4 passes that nil through to convert_value/2. Before this migration the OTLP value oneof was left unset, but these new clauses now emit a real 0/0.0 datapoint instead, so missing measurements are silently reported as zero-valued gauges. That corrupts exported metrics in exactly the cases this comment says we are trying to preserve.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
This needs to be addressed: we must avoid emitting data points using default values where the source measurement didn't have any datapoints to begin with.
| @spec decode(binary()) :: {:ok, t()} | {:error, any()} | ||
| def decode(bytes) do | ||
| {:ok, decode!(bytes)} |
There was a problem hiding this comment.
Preserve
decode/1 return shape on public proto modules
The generated OtelMetricExporter.Opentelemetry.Proto.* modules are exposed under this library's namespace, and the previous use Protobuf implementation returned the decoded struct directly from decode/1. After regeneration, ExportMetricsServiceRequest.decode/1 now returns {:ok, struct} instead, so any downstream code still doing what our pre-migration call sites did—pipe bytes into decode/1 and pattern-match on %ExportMetricsServiceRequest{}—will break at runtime after upgrading. If this release is meant to be source-compatible, these modules need a shim or the old API preserved.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
The change in the return value shape looks unjustified. Revert it to keep API compatibility with existing users of the library.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
P1: Skip nil measurements instead of coercing to zero. When
extract_measurement returns nil (e.g. measurement key not in event),
handle_metric now skips writing to ETS rather than emitting a datapoint
with a zero default value. The convert_value(nil, ...) fallback clauses
are removed since nil values no longer reach that code path.
P2: Restore decode/1 to return the struct directly instead of {:ok, struct},
preserving API compatibility with the previous protobuf-based implementation.
P3: Remove 8 unused protox-generated modules (LogRecordFlags, DataPointFlags,
ExportLogsPartialSuccess, ExportLogsServiceResponse, ExportMetricsPartialSuccess,
ExportMetricsServiceResponse, LogsData, MetricsData) reducing the generated
file from ~10.7K to ~9.2K lines. Modules referenced transitively by used code
(Exemplar, ExponentialHistogram*, Summary*, etc.) are retained.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Follow-up addressing review feedbackPushed 3 commits addressing the review feedback: P1 (nil measurements): P2 (decode/1 return shape): All P3 (large generated file): Removed 8 unused modules (~1,460 lines, 13.8% reduction). The file went from ~10.7K to ~9.2K lines. Transitive dependency analysis determined that 7 additional modules (Exemplar, ExponentialHistogram, ExponentialHistogramDataPoint, ExponentialHistogramDataPoint.Buckets, Summary, SummaryDataPoint, SummaryDataPoint.ValueAtQuantile) must be retained because they are referenced by used modules -- for example, Justification for the single-file approach: Protox generates all modules for a given set of All 45 tests pass. |
Summary
protobufdependency withprotoxto eliminate the duplicateGoogle.Protobuf.*module conflict described in Unify protobuf libraries to remove protobuf version pin electric#4018mix protox.generatefrom the vendored OpenTelemetry.protofiles (submodule)--warnings-as-errorsKey changes
{:protobuf, "~> 0.15"}→{:protox, "~> 2.0"}Protobuf.encode_to_iodata/1→Protox.encode!/1(returns{iodata, size})Protobuf.decode/2→Protox.decode!/2,Module.decode/1→Module.decode!/1SeverityNumber.value(:ATOM)→ just:ATOM(protox enum fields accept atoms directly)Protobuf.EncodeError→Protox.EncodingErrorGenerated code
The 6 old
.pb.exfiles (584 lines) were replaced with a singleopentelemetry_proto.ex(10,739 lines) generated bymix protox.generate. The generated file includes all OpenTelemetry proto modules (metrics, logs, common, resource, collector services). All module names are preserved with theOtelMetricExporter.Opentelemetry.Proto.*namespace.Test plan
mix compile --warnings-as-errorspasses🤖 Generated with Claude Code