foam-otel 1.9.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +24 -25
- data/lib/foam/otel/version.rb +9 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 767e21dce7e53eb8a74e430c736f2ba94e22c882022733fff7fb8edb058c118e
|
|
4
|
+
data.tar.gz: 4d9e7b6789d79daec4eb0482a22ac68520263c0a267e1b4e4def7eae97d9e642
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4512202149fa0ee2b50093b7485b07373a09ed29315b6489d3e59d0c111ecf3d023e77e49f9af271ca97df33210e2028ba3376e4a43516284bd6f0fe195a8627
|
|
7
|
+
data.tar.gz: 9d15c2c183dfdac3ca20f0a3eccae5c6f2e45134206a697604a1b70e7a9046c775d0b5e805662a162aee2b0d89e62f810cdea8e43a72b9f15db783f1b07ccb0d
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Foam's OpenTelemetry core for Ruby services. A thin, safe wrapper over the
|
|
4
4
|
official OpenTelemetry libraries: foam owns the pipeline (providers, batch
|
|
5
|
-
processors, OTLP export to the foam
|
|
5
|
+
processors, OTLP export to the foam endpoint), turns on automatic
|
|
6
6
|
tier-1/2 instrumentation, and hands you a small set of never-throw helpers —
|
|
7
7
|
and nothing else. **Redaction is fully opt-in above two always-on exceptions:
|
|
8
8
|
by default foam captures every value RAW** (no PII preset) **except (1) the
|
|
@@ -42,7 +42,8 @@ gem "opentelemetry-instrumentation-graphql" # e.g. GraphQL
|
|
|
42
42
|
gem "opentelemetry-instrumentation-resque" # e.g. Resque
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
**Supported versions** (tested in CI, `spec/version_spec.rb`): Ruby **>= 3.
|
|
45
|
+
**Supported versions** (tested in CI, `spec/version_spec.rb`): Ruby **>= 3.4**
|
|
46
|
+
(the version the CI matrix runs — the floor follows the tested matrix);
|
|
46
47
|
OpenTelemetry API **`opentelemetry-api` ~> 1.1** (1.x). The metrics and logs
|
|
47
48
|
SDKs are pre-1.0 upstream (metrics alpha, logs development) and are pinned with
|
|
48
49
|
pessimistic constraints; foam wraps them behind stable helpers so app code never
|
|
@@ -69,7 +70,7 @@ Foam::Otel.init(
|
|
|
69
70
|
```
|
|
70
71
|
|
|
71
72
|
**Outcome**: foam registers the tracer/meter/logger providers, exports OTLP to
|
|
72
|
-
the foam
|
|
73
|
+
the foam endpoint, and auto-activates the **universal floor** — the
|
|
73
74
|
official rack/rails instrumentation plus the bundled HTTP (Net::HTTP/Faraday),
|
|
74
75
|
datastore (pg/mysql2/redis/mongo), and Sidekiq instrumentations — each
|
|
75
76
|
presence-gated, and gated on foam owning the traces slot (a foreign-owned
|
|
@@ -111,7 +112,7 @@ turns keep their tool names/arguments and tool-result turns keep their
|
|
|
111
112
|
`tool_call_id` linkage inside the message content. `gen_ai.operation.name`
|
|
112
113
|
(and the `{operation} {model}` span name) follows the semconv operation for
|
|
113
114
|
each API shape — `chat` for the OpenAI/Anthropic/ruby_llm chat seams,
|
|
114
|
-
`generate_content` for Gemini's generateContent,
|
|
115
|
+
`generate_content` for Gemini's generateContent, identical to foam's
|
|
115
116
|
js/python Gemini paths (**wire change in 1.2.1**: Gemini spans previously
|
|
116
117
|
said `chat`). Covered: the official `openai` SDK
|
|
117
118
|
(chat.completions.create + responses.create), the official `anthropic` SDK
|
|
@@ -148,8 +149,8 @@ listed request and response headers as
|
|
|
148
149
|
> **Honest limit (deliberate divergence from foam's js/python cores):**
|
|
149
150
|
> Ruby inbound captures the **named default list below, NOT all headers** —
|
|
150
151
|
> the official gem's options are an enumerated allowlist with no
|
|
151
|
-
> capture-all form, and that official option is the chosen seam
|
|
152
|
-
>
|
|
152
|
+
> capture-all form, and that official option is the chosen seam.
|
|
153
|
+
> A custom header outside the list is **not captured** unless
|
|
153
154
|
> you extend the list (recipe below).
|
|
154
155
|
|
|
155
156
|
The default lists (`Foam::Otel::HeaderCapture::DEFAULT_REQUEST_HEADERS` /
|
|
@@ -321,7 +322,7 @@ not captured — inbound only.
|
|
|
321
322
|
| `name:` | String | yes | — | `service.name`. Blank → raises at boot. |
|
|
322
323
|
| `environment:` | String | yes | — | `deployment.environment.name`, exported verbatim. A value outside `{production, staging, development, test}` warns but is never rewritten. Blank → raises. |
|
|
323
324
|
| `enabled:` | Boolean | yes | — | The config switch. `false` = fully inert (no SDK, no providers, no network, helpers no-op). `true` = export, in EVERY environment. No default — you write the logic. |
|
|
324
|
-
| `token:` | String | when enabled | — | `Authorization: Bearer` for export. Required (and validated) only when `enabled: true`; wired explicitly from your secret source — never an env fallback read by the gem. **
|
|
325
|
+
| `token:` | String | when enabled | — | `Authorization: Bearer` for export. Required (and validated) only when `enabled: true`; wired explicitly from your secret source — never an env fallback read by the gem. **The convention across all foam SDKs: read it from the `FOAM_OTEL_TOKEN` env var.** Blank while enabled → raises at boot. |
|
|
325
326
|
| `version:` | String | no | nil | `service.version`, verbatim (git SHA recommended). Missing → warns and continues. Never detected at runtime. |
|
|
326
327
|
| `redact:` | Hash | no | nil | The grouped redaction object (1.5.0, the preferred surface): `{ secrets: [...], pii: [...], detect: [...] }` — symbol or string keys. `secrets:` has `redact_keys` semantics (tail mask) and `pii:` has `redact_pii_keys` semantics (full `[REDACTED]`); when both a legacy option and its `redact` field are set, the lists UNION. `detect:` is the opt-in PII detection tier's entity list — value-shape detection with typed placeholders (see "PII detection (opt-in)" below). An unknown field, a non-Array value, or an unknown `detect` entity name raises at boot. Absent (the default) → behavior byte-identical to before. |
|
|
327
328
|
| `redact_keys:` | Array<String> | no | `[]` | Alias — the preferred spelling is `redact: { secrets: [...] }` (same semantics; the lists union when both are set). The ONLY field names tail-masked (shape-preserving, e.g. `********f456`). Opt-in and ADDITIVE on top of the always-on credential floor — empty (the default) means no masking beyond the floor. Matches by case-insensitive substring, including keys nested in structured values and query-string keys. A key that is also on the floor stays fully `[REDACTED]` (the floor wins; it is never downgraded to a tail). |
|
|
@@ -432,8 +433,7 @@ override is the operator-level `OTEL_EXPORTER_OTLP_ENDPOINT` env var (below).
|
|
|
432
433
|
|
|
433
434
|
## The default credential denylist (the always-on floor)
|
|
434
435
|
|
|
435
|
-
|
|
436
|
-
`docs/decisions/credential-denylist-design.md`; frozen fixture:
|
|
436
|
+
Always on in every foam SDK, identical everywhere (frozen fixture:
|
|
437
437
|
`contract/credential-denylist.json`). This is the ONE exception to foam's
|
|
438
438
|
raw-by-default capture, and it has **no off switch** — no init option, no env
|
|
439
439
|
var, and no door-2 parameter can disable, shrink, or re-spell it.
|
|
@@ -482,13 +482,13 @@ byte-identical raw, exactly as documented everywhere else in this README.
|
|
|
482
482
|
|
|
483
483
|
**Why.** Coverage-over-masking remains the mission, but raw `Authorization`
|
|
484
484
|
headers, cookies, and API keys on the wire are a breach in waiting for every
|
|
485
|
-
customer at once —
|
|
486
|
-
this list) as non-negotiable. The list is byte-identical in every foam
|
|
487
|
-
and gate-checked in CI against the
|
|
485
|
+
customer at once — foam carves out exactly this list (and only
|
|
486
|
+
this list) as non-negotiable. The list is byte-identical in every foam SDK
|
|
487
|
+
and gate-checked in CI against the shipped fixture
|
|
488
488
|
(`spec/credential_floor_spec.rb`).
|
|
489
489
|
|
|
490
|
-
**
|
|
491
|
-
concept in every
|
|
490
|
+
**Param names across the foam SDKs** (the customer options above the floor,
|
|
491
|
+
identical concept in every SDK — the floor itself has NO init surface anywhere):
|
|
492
492
|
|
|
493
493
|
| Concept | js/otel | js/browser | python | ruby | java |
|
|
494
494
|
|---|---|---|---|---|---|
|
|
@@ -517,8 +517,7 @@ The credential floor masks by NAME and is deliberately value-shape-blind — a
|
|
|
517
517
|
live AWS key under the field name `note` would sail past it. Foam telemetry is
|
|
518
518
|
read downstream by LLMs, so a leaked credential is exfiltratable by prompt
|
|
519
519
|
injection; "no leakage at all" is the bar. The value-pattern secret layer is
|
|
520
|
-
the second always-on control
|
|
521
|
-
`docs/decisions/security-fixes-design.md`):
|
|
520
|
+
the second always-on control:
|
|
522
521
|
|
|
523
522
|
**What it masks.** Credential-SHAPED value spans, regardless of the field
|
|
524
523
|
name they hide under: AWS access-key ids and keyword-anchored AWS secrets,
|
|
@@ -561,8 +560,8 @@ value rather than shipping it raw.
|
|
|
561
560
|
|
|
562
561
|
**Provenance.** The ruleset derives from MIT/Apache-licensed OSS secret
|
|
563
562
|
scanners (gitleaks, detect-secrets, secretlint) — see `THIRD-PARTY-NOTICES`.
|
|
564
|
-
Rules are frozen module constants, byte-consistent across
|
|
565
|
-
|
|
563
|
+
Rules are frozen module constants, byte-consistent across all foam SDKs —
|
|
564
|
+
not configurable per app.
|
|
566
565
|
|
|
567
566
|
> **Migration note — 1.4.0 (minor): value-pattern secret masking + redaction
|
|
568
567
|
> coverage fix + TLS pin.** foam now masks credential-SHAPED values
|
|
@@ -589,9 +588,9 @@ The floor and the secret layer protect credentials. PII in VALUES — an email
|
|
|
589
588
|
address inside a log line, a card number inside an exception message — still
|
|
590
589
|
exports RAW by default, because coverage-over-masking is the mission and only
|
|
591
590
|
you know your privacy posture. As of 1.5.0 you can opt into value-shape PII
|
|
592
|
-
detection per entity, via `redact: { detect: [...] }` (
|
|
593
|
-
|
|
594
|
-
placeholders are byte-identical in every foam
|
|
591
|
+
detection per entity, via `redact: { detect: [...] }` (frozen fixture:
|
|
592
|
+
`contract/pii-detect.json` — the entity names and
|
|
593
|
+
placeholders are byte-identical in every foam SDK and gate-checked in CI by
|
|
595
594
|
`spec/pii_detect_spec.rb`). Nothing detects unless you list the entity —
|
|
596
595
|
an empty/absent `detect` list is exactly today's behavior.
|
|
597
596
|
|
|
@@ -696,7 +695,7 @@ at-exit flush. Anything a hook needs from the request/job thread
|
|
|
696
695
|
attribute at capture time (see the `additional_span_processors` stamper
|
|
697
696
|
pattern); thread-locals are gone by the time the hook runs.
|
|
698
697
|
|
|
699
|
-
Boot validation is strict
|
|
698
|
+
Boot validation is strict: a non-callable — or a **lambda/Method
|
|
700
699
|
whose signature cannot accept one positional argument** (e.g. a Sentry-port
|
|
701
700
|
`->(event, hint) { ... }` with two required params, or a required keyword)
|
|
702
701
|
— raises `ArgumentError` at `init`, because it would otherwise fault on
|
|
@@ -963,7 +962,7 @@ which every tap applies with zero configuration; `diagnostics:` is tap-scoped
|
|
|
963
962
|
narration). Construction
|
|
964
963
|
validates loudly at boot and NEVER
|
|
965
964
|
throws afterwards — a failure inside a tap can never break their pipeline.
|
|
966
|
-
|
|
965
|
+
Naming across the foam SDKs (pinned by `spec/export_surface_spec.rb`):
|
|
967
966
|
`create_ingest_span_processor` = `createFoamIngestSpanProcessor`,
|
|
968
967
|
`create_ingest_log_record_processor` = `createFoamIngestLogRecordProcessor`,
|
|
969
968
|
`create_ingest_metric_reader` = `createFoamIngestMetricReader`.
|
|
@@ -1098,8 +1097,8 @@ end
|
|
|
1098
1097
|
|
|
1099
1098
|
| Var | Posture |
|
|
1100
1099
|
| --- | --- |
|
|
1101
|
-
| `OTEL_SDK_DISABLED=true` | HONORED — full kill switch, supersedes `enabled: true` (matched trimmed + case-insensitive, so `TRUE` / ` true ` also kill —
|
|
1102
|
-
| `OTEL_EXPORTER_OTLP_ENDPOINT` | HONORED — the one operator-level override of the pinned
|
|
1100
|
+
| `OTEL_SDK_DISABLED=true` | HONORED — full kill switch, supersedes `enabled: true` (matched trimmed + case-insensitive, so `TRUE` / ` true ` also kill — this one emergency switch behaves the same in every foam SDK). Door-2 ingest entries honor it too: construction returns an inert instance (read once at construction; changing it implies a restart). |
|
|
1101
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | HONORED — the one operator-level override of the pinned foam endpoint (for foam's own conformance rig / enterprise egress). Active → loud `[foam]` warning naming the destination. Applies to door-2 taps identically (and moves the host the required loop step must name). |
|
|
1103
1102
|
| `OTEL_PROPAGATORS=none` | HONORED — turns trace propagation OFF (links lost) while telemetry keeps flowing; warns. Any other value warns and is ignored (foam's propagator set is fixed: W3C tracecontext + baggage). |
|
|
1104
1103
|
| `OTEL_BSP_SCHEDULE_DELAY` / `OTEL_BLRP_SCHEDULE_DELAY` / `OTEL_METRIC_EXPORT_INTERVAL` | HONORED — batch cadence, read natively by the upstream SDK. |
|
|
1105
1104
|
| `FOAM_CAPTURE_PAYLOADS` | HONORED — the operator clamp over the `capture_payloads:` init option (`off`/`errors`/`always`, case-insensitive), overriding it in BOTH directions with one loud `[foam]` line when it changes the mode. An invalid value warns and falls back to the init option (never crashes a boot). This is the ONE foam-named env var the gem reads — an override valve over an init-declared option, never an on/off switch, token, or config fallback (those still arrive only through `init`'s explicit arguments). Read once at init; changing it implies a restart. |
|
data/lib/foam/otel/version.rb
CHANGED
|
@@ -186,6 +186,14 @@ module Foam
|
|
|
186
186
|
# ORIGINAL resource/scope are force-restored onto every survivor
|
|
187
187
|
# after the pipeline (identity is not hook-writable — the Go port's
|
|
188
188
|
# contract; README updated).
|
|
189
|
-
|
|
189
|
+
# 2.0.0: RUNTIME FLOOR RAISE (label-follows-tested-matrix ruling
|
|
190
|
+
# 2026-07-29). required_ruby_version >= 3.1 -> >= 3.4 — the version the
|
|
191
|
+
# CI matrix actually runs. The 3.1 floor was an unproven published
|
|
192
|
+
# promise: no CI leg ran below 3.4, and on 3.1–3.2 (both EOL) Bundler
|
|
193
|
+
# resolves an OLDER upstream otel gem set than the proven lockfile —
|
|
194
|
+
# a combination never tested. MAJOR: narrowing the supported-runtime
|
|
195
|
+
# label is breaking for installs on the dropped versions. No wire/API
|
|
196
|
+
# change — every 1.x contract above still holds.
|
|
197
|
+
VERSION = "2.0.0"
|
|
190
198
|
end
|
|
191
199
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foam-otel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Foam
|
|
@@ -422,7 +422,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
422
422
|
requirements:
|
|
423
423
|
- - ">="
|
|
424
424
|
- !ruby/object:Gem::Version
|
|
425
|
-
version: '3.
|
|
425
|
+
version: '3.4'
|
|
426
426
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
427
427
|
requirements:
|
|
428
428
|
- - ">="
|