Class: Foam::Otel::RedactingMetricsExporter

Inherits:
Object
  • Object
show all
Defined in:
lib/foam/otel/redacting_exporter.rb

Overview

The metrics twin, added for door 2 (fleet contract ruling): door 1 masks metric attributes at capture, which FOREIGN instruments never pass — the ingest metric path runs the floor here, on foam's collected copy, before serialization and before any retry buffer. Same fail-closed posture as the span/log exporters: a metric whose rebuild fails is DROPPED loudly (never exported raw) and the batch reports FAILURE.

Also forwards reset — PeriodicMetricReader#after_fork calls exporter.reset to re-establish the OTLP HTTP connection in a forked child; a wrapper that swallowed it would leave door-2 metric taps dark in every Puma worker (GOTCHAS R7).

Instance Method Summary collapse

Constructor Details

#initialize(inner, config) ⇒ RedactingMetricsExporter

Returns a new instance of RedactingMetricsExporter.



103
104
105
106
# File 'lib/foam/otel/redacting_exporter.rb', line 103

def initialize(inner, config)
  @inner = inner
  @config = config
end

Instance Method Details

#export(metrics, timeout: nil) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/foam/otel/redacting_exporter.rb', line 108

def export(metrics, timeout: nil)
  batch = metrics.to_a
  masked = batch.filter_map { |md| Redaction.mask_metric_data(md, @config) }
  dropped = batch.length - masked.length
  if dropped.positive?
    Diagnostics.warn("redaction failed for #{dropped} metric(s) — dropped rather than exported " \
                     "unmasked (rule 14 fail-closed)")
    @inner.export(masked, timeout: timeout) unless masked.empty?
    return OpenTelemetry::SDK::Metrics::Export::FAILURE
  end
  @inner.export(masked, timeout: timeout)
rescue StandardError, SystemStackError
  Diagnostics.warn("metric redaction raised past its guards — batch dropped (fail-closed, rule 14/15)")
  OpenTelemetry::SDK::Metrics::Export::FAILURE
end

#force_flush(timeout: nil) ⇒ Object



124
# File 'lib/foam/otel/redacting_exporter.rb', line 124

def force_flush(timeout: nil) = @inner.force_flush(timeout: timeout)

#resetObject



127
128
129
# File 'lib/foam/otel/redacting_exporter.rb', line 127

def reset
  @inner.reset if @inner.respond_to?(:reset)
end

#shutdown(timeout: nil) ⇒ Object



125
# File 'lib/foam/otel/redacting_exporter.rb', line 125

def shutdown(timeout: nil) = @inner.shutdown(timeout: timeout)