errorbar-tracing 0.2.0__tar.gz
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.
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: errorbar-tracing
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: errorbar tracing — standard OpenTelemetry, curated. One install, one line; eject anytime, your spans don't change.
|
|
5
|
+
Project-URL: Repository, https://github.com/omnia-v/omnia-tracing
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27
|
|
9
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic>=0.30
|
|
10
|
+
Requires-Dist: opentelemetry-instrumentation-google-generativeai>=0.30
|
|
11
|
+
Requires-Dist: opentelemetry-instrumentation-langchain>=0.30
|
|
12
|
+
Requires-Dist: opentelemetry-instrumentation-openai>=0.30
|
|
13
|
+
Requires-Dist: opentelemetry-sdk>=1.27
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# errorbar-tracing
|
|
17
|
+
|
|
18
|
+
**Standard OpenTelemetry, curated.** One install, one line, and your LLM traffic streams to [errorbar](https://platform.omnia-voice.com) — where you grade it, calibrate a judge against your own standards, and find out **with confidence intervals** whether a cheaper model holds up on your production traffic.
|
|
19
|
+
|
|
20
|
+
This package contains **no instrumentation code of its own**. It pins and configures the ecosystem's standard OpenTelemetry instrumentations — which gives it a property no other tracing SDK offers: **you can uninstall it without losing your instrumentation.** The identical setup in vanilla OTel is documented below; your spans are byte-for-byte the same either way, and nothing proprietary ever goes on the wire.
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install errorbar-tracing
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Use
|
|
29
|
+
|
|
30
|
+
Call once at startup, **before constructing any LLM client**:
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from errorbar_tracing import setup
|
|
34
|
+
|
|
35
|
+
tracing = setup() # reads ERRORBAR_API_KEY and ERRORBAR_TAG
|
|
36
|
+
print(tracing.instrumented) # e.g. ['openai', 'anthropic'] — only what's installed
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Short-lived scripts should call `tracing.shutdown()` before exit to flush pending spans; long-running servers can skip it.
|
|
40
|
+
|
|
41
|
+
## What gets captured
|
|
42
|
+
|
|
43
|
+
OpenAI, Anthropic, Gemini, and LangChain calls — automatically, and **only for libraries actually installed** (the `instrumented` list tells you exactly which). Successful calls, streamed calls, and **failed** calls (stored as ERROR trace structure — the most valuable signal there is, and the one status-code dashboards can't see).
|
|
44
|
+
|
|
45
|
+
Your inference does **not** move: requests keep going to your current provider; only trace telemetry flows to errorbar.
|
|
46
|
+
|
|
47
|
+
## Configuration
|
|
48
|
+
|
|
49
|
+
| Env var | Meaning | Default |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| `ERRORBAR_API_KEY` | errorbar API key — **required**; `setup()` raises rather than exporting nowhere silently | — |
|
|
52
|
+
| `ERRORBAR_TAG` | Population tag: one tag = one evaluation population in errorbar | unset |
|
|
53
|
+
| `ERRORBAR_OTLP_ENDPOINT` | OTLP/HTTP traces endpoint | `https://gateway.errorbar.ai/v1/traces` |
|
|
54
|
+
| `OTEL_SERVICE_NAME` | Standard OTel service name | unset |
|
|
55
|
+
|
|
56
|
+
All options can also be passed to `setup()` directly; explicit options beat env vars.
|
|
57
|
+
|
|
58
|
+
## The eject guarantee
|
|
59
|
+
|
|
60
|
+
Remove this package and wire the same standard pieces yourself — identical spans, same endpoint, nothing lost:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
import os
|
|
64
|
+
from opentelemetry.sdk.resources import Resource
|
|
65
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
66
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
67
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
68
|
+
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
|
|
69
|
+
|
|
70
|
+
provider = TracerProvider(
|
|
71
|
+
resource=Resource.create({"service.name": "my-service", "omnia.tag": "my-agent"})
|
|
72
|
+
)
|
|
73
|
+
provider.add_span_processor(
|
|
74
|
+
BatchSpanProcessor(
|
|
75
|
+
OTLPSpanExporter(
|
|
76
|
+
endpoint="https://gateway.errorbar.ai/v1/traces",
|
|
77
|
+
headers={"Authorization": f"Bearer {os.environ['ERRORBAR_API_KEY']}"},
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
AnthropicInstrumentor().instrument(tracer_provider=provider)
|
|
82
|
+
# ...and the other instrumentors for whichever libraries you use
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Already emitting OpenTelemetry (Pydantic AI, an existing OTel setup)? You don't need this package at all — three env vars point your existing exporter at errorbar. See the [OTLP ingest reference](https://docs.omnia-voice.com/reference/otlp-ingest).
|
|
86
|
+
|
|
87
|
+
## Privacy
|
|
88
|
+
|
|
89
|
+
Span **structure** is always stored. Model-call **content** (prompts/completions) is stored only if your errorbar workspace has request logging enabled, under your retention window, with the same scrubbing and size caps as gateway traffic.
|
|
90
|
+
|
|
91
|
+
## Verify your setup — get a receipt, not a hope
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
ERRORBAR_API_KEY=sk_... sh -c "$(curl -fsSL https://platform.omnia-voice.com/setup.sh)"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Proves the key works, confirms traces are actually landing, and names your one next step. Instrumentation that fails silently is the industry default; this is the alternative.
|
|
98
|
+
|
|
99
|
+
## Links
|
|
100
|
+
|
|
101
|
+
- [Docs](https://docs.omnia-voice.com/reference/tracing-sdk) · [Platform](https://platform.omnia-voice.com) · [Node package](https://www.npmjs.com/package/@omnia-voice/tracing)
|
|
102
|
+
|
|
103
|
+
Apache-2.0
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# errorbar-tracing
|
|
2
|
+
|
|
3
|
+
**Standard OpenTelemetry, curated.** One install, one line, and your LLM traffic streams to [errorbar](https://platform.omnia-voice.com) — where you grade it, calibrate a judge against your own standards, and find out **with confidence intervals** whether a cheaper model holds up on your production traffic.
|
|
4
|
+
|
|
5
|
+
This package contains **no instrumentation code of its own**. It pins and configures the ecosystem's standard OpenTelemetry instrumentations — which gives it a property no other tracing SDK offers: **you can uninstall it without losing your instrumentation.** The identical setup in vanilla OTel is documented below; your spans are byte-for-byte the same either way, and nothing proprietary ever goes on the wire.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install errorbar-tracing
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Use
|
|
14
|
+
|
|
15
|
+
Call once at startup, **before constructing any LLM client**:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from errorbar_tracing import setup
|
|
19
|
+
|
|
20
|
+
tracing = setup() # reads ERRORBAR_API_KEY and ERRORBAR_TAG
|
|
21
|
+
print(tracing.instrumented) # e.g. ['openai', 'anthropic'] — only what's installed
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Short-lived scripts should call `tracing.shutdown()` before exit to flush pending spans; long-running servers can skip it.
|
|
25
|
+
|
|
26
|
+
## What gets captured
|
|
27
|
+
|
|
28
|
+
OpenAI, Anthropic, Gemini, and LangChain calls — automatically, and **only for libraries actually installed** (the `instrumented` list tells you exactly which). Successful calls, streamed calls, and **failed** calls (stored as ERROR trace structure — the most valuable signal there is, and the one status-code dashboards can't see).
|
|
29
|
+
|
|
30
|
+
Your inference does **not** move: requests keep going to your current provider; only trace telemetry flows to errorbar.
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
| Env var | Meaning | Default |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| `ERRORBAR_API_KEY` | errorbar API key — **required**; `setup()` raises rather than exporting nowhere silently | — |
|
|
37
|
+
| `ERRORBAR_TAG` | Population tag: one tag = one evaluation population in errorbar | unset |
|
|
38
|
+
| `ERRORBAR_OTLP_ENDPOINT` | OTLP/HTTP traces endpoint | `https://gateway.errorbar.ai/v1/traces` |
|
|
39
|
+
| `OTEL_SERVICE_NAME` | Standard OTel service name | unset |
|
|
40
|
+
|
|
41
|
+
All options can also be passed to `setup()` directly; explicit options beat env vars.
|
|
42
|
+
|
|
43
|
+
## The eject guarantee
|
|
44
|
+
|
|
45
|
+
Remove this package and wire the same standard pieces yourself — identical spans, same endpoint, nothing lost:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
import os
|
|
49
|
+
from opentelemetry.sdk.resources import Resource
|
|
50
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
51
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
52
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
53
|
+
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
|
|
54
|
+
|
|
55
|
+
provider = TracerProvider(
|
|
56
|
+
resource=Resource.create({"service.name": "my-service", "omnia.tag": "my-agent"})
|
|
57
|
+
)
|
|
58
|
+
provider.add_span_processor(
|
|
59
|
+
BatchSpanProcessor(
|
|
60
|
+
OTLPSpanExporter(
|
|
61
|
+
endpoint="https://gateway.errorbar.ai/v1/traces",
|
|
62
|
+
headers={"Authorization": f"Bearer {os.environ['ERRORBAR_API_KEY']}"},
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
AnthropicInstrumentor().instrument(tracer_provider=provider)
|
|
67
|
+
# ...and the other instrumentors for whichever libraries you use
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Already emitting OpenTelemetry (Pydantic AI, an existing OTel setup)? You don't need this package at all — three env vars point your existing exporter at errorbar. See the [OTLP ingest reference](https://docs.omnia-voice.com/reference/otlp-ingest).
|
|
71
|
+
|
|
72
|
+
## Privacy
|
|
73
|
+
|
|
74
|
+
Span **structure** is always stored. Model-call **content** (prompts/completions) is stored only if your errorbar workspace has request logging enabled, under your retention window, with the same scrubbing and size caps as gateway traffic.
|
|
75
|
+
|
|
76
|
+
## Verify your setup — get a receipt, not a hope
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
ERRORBAR_API_KEY=sk_... sh -c "$(curl -fsSL https://platform.omnia-voice.com/setup.sh)"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Proves the key works, confirms traces are actually landing, and names your one next step. Instrumentation that fails silently is the industry default; this is the alternative.
|
|
83
|
+
|
|
84
|
+
## Links
|
|
85
|
+
|
|
86
|
+
- [Docs](https://docs.omnia-voice.com/reference/tracing-sdk) · [Platform](https://platform.omnia-voice.com) · [Node package](https://www.npmjs.com/package/@omnia-voice/tracing)
|
|
87
|
+
|
|
88
|
+
Apache-2.0
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "errorbar-tracing"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "errorbar tracing — standard OpenTelemetry, curated. One install, one line; eject anytime, your spans don't change."
|
|
9
|
+
license = "Apache-2.0"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"opentelemetry-sdk>=1.27",
|
|
14
|
+
"opentelemetry-exporter-otlp-proto-http>=1.27",
|
|
15
|
+
"opentelemetry-instrumentation-openai>=0.30",
|
|
16
|
+
"opentelemetry-instrumentation-anthropic>=0.30",
|
|
17
|
+
"opentelemetry-instrumentation-google-generativeai>=0.30",
|
|
18
|
+
"opentelemetry-instrumentation-langchain>=0.30",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Repository = "https://github.com/omnia-v/omnia-tracing"
|
|
23
|
+
|
|
24
|
+
[dependency-groups]
|
|
25
|
+
dev = ["pytest>=8"]
|
|
26
|
+
|
|
27
|
+
[tool.hatch.build.targets.sdist]
|
|
28
|
+
# Explicit allowlist: hatchling's default packs the project DIR, which once
|
|
29
|
+
# shipped a local .env inside a published sdist. Never again — list what
|
|
30
|
+
# ships; everything else stays home.
|
|
31
|
+
include = ["src/errorbar_tracing", "tests", "README.md", "pyproject.toml"]
|
|
32
|
+
|
|
33
|
+
[tool.hatch.build.targets.wheel]
|
|
34
|
+
packages = ["src/errorbar_tracing"]
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""errorbar tracing — standard OpenTelemetry, curated.
|
|
2
|
+
|
|
3
|
+
One install, one line; eject anytime, your spans don't change. This package
|
|
4
|
+
contains NO instrumentation code of its own: it pins and configures standard,
|
|
5
|
+
ecosystem-maintained OpenTelemetry pieces. The identical setup without this
|
|
6
|
+
package is documented in docs/eject.md.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
|
|
14
|
+
DEFAULT_ENDPOINT = "https://gateway.errorbar.ai/v1/traces"
|
|
15
|
+
TAG_ATTRIBUTE = "omnia.tag"
|
|
16
|
+
|
|
17
|
+
__all__ = ["setup", "resolve_config", "ResolvedConfig", "Tracing", "DEFAULT_ENDPOINT", "TAG_ATTRIBUTE"]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class ResolvedConfig:
|
|
22
|
+
endpoint: str
|
|
23
|
+
headers: dict[str, str]
|
|
24
|
+
service_name: str | None
|
|
25
|
+
resource_attributes: dict[str, str] = field(default_factory=dict)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def resolve_config(
|
|
29
|
+
api_key: str | None = None,
|
|
30
|
+
tag: str | None = None,
|
|
31
|
+
service_name: str | None = None,
|
|
32
|
+
endpoint: str | None = None,
|
|
33
|
+
env: dict[str, str] | None = None,
|
|
34
|
+
) -> ResolvedConfig:
|
|
35
|
+
"""Pure configuration assembly — unit-testable without starting a pipeline."""
|
|
36
|
+
e = os.environ if env is None else env
|
|
37
|
+
key = api_key or e.get("ERRORBAR_API_KEY") or e.get("OMNIA_API_KEY")
|
|
38
|
+
if not key:
|
|
39
|
+
raise ValueError(
|
|
40
|
+
"errorbar-tracing: no API key. Pass setup(api_key=...) or set ERRORBAR_API_KEY (OMNIA_API_KEY still works). "
|
|
41
|
+
"Refusing to start a tracer that exports nowhere."
|
|
42
|
+
)
|
|
43
|
+
resource_attributes: dict[str, str] = {}
|
|
44
|
+
resolved_tag = tag or e.get("ERRORBAR_TAG") or e.get("OMNIA_TAG")
|
|
45
|
+
if resolved_tag:
|
|
46
|
+
resource_attributes[TAG_ATTRIBUTE] = resolved_tag
|
|
47
|
+
return ResolvedConfig(
|
|
48
|
+
endpoint=endpoint
|
|
49
|
+
or e.get("ERRORBAR_OTLP_ENDPOINT")
|
|
50
|
+
or e.get("OMNIA_OTLP_ENDPOINT")
|
|
51
|
+
or DEFAULT_ENDPOINT,
|
|
52
|
+
headers={"Authorization": f"Bearer {key}"},
|
|
53
|
+
service_name=service_name or e.get("OTEL_SERVICE_NAME"),
|
|
54
|
+
resource_attributes=resource_attributes,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Tracing:
|
|
59
|
+
"""Handle returned by setup(): shutdown() flushes and stops.
|
|
60
|
+
|
|
61
|
+
`instrumented` names the libraries actually being traced — the ones both
|
|
62
|
+
installed in this environment and successfully instrumented."""
|
|
63
|
+
|
|
64
|
+
def __init__(self, provider, instrumented: list[str]) -> None:
|
|
65
|
+
self._provider = provider
|
|
66
|
+
self.instrumented = instrumented
|
|
67
|
+
|
|
68
|
+
def shutdown(self) -> None:
|
|
69
|
+
self._provider.shutdown()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def setup(
|
|
73
|
+
api_key: str | None = None,
|
|
74
|
+
tag: str | None = None,
|
|
75
|
+
service_name: str | None = None,
|
|
76
|
+
endpoint: str | None = None,
|
|
77
|
+
) -> Tracing:
|
|
78
|
+
"""Start standard OpenTelemetry tracing, exporting to errorbar.
|
|
79
|
+
|
|
80
|
+
Call ONCE, at startup, before constructing LLM clients. Instruments
|
|
81
|
+
OpenAI, Anthropic, Gemini and LangChain via the ecosystem's standard
|
|
82
|
+
instrumentation packages.
|
|
83
|
+
"""
|
|
84
|
+
config = resolve_config(api_key, tag, service_name, endpoint)
|
|
85
|
+
|
|
86
|
+
# Imports live here, not module top: `import errorbar_tracing` must stay
|
|
87
|
+
# side-effect free so resolve_config is usable (and testable) alone.
|
|
88
|
+
from opentelemetry.sdk.resources import Resource
|
|
89
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
90
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
91
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
92
|
+
|
|
93
|
+
attrs: dict[str, str] = dict(config.resource_attributes)
|
|
94
|
+
if config.service_name:
|
|
95
|
+
attrs["service.name"] = config.service_name
|
|
96
|
+
provider = TracerProvider(resource=Resource.create(attrs))
|
|
97
|
+
provider.add_span_processor(
|
|
98
|
+
BatchSpanProcessor(
|
|
99
|
+
OTLPSpanExporter(endpoint=config.endpoint, headers=config.headers)
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Each instrumentation package imports its TARGET library at import time,
|
|
104
|
+
# so instrument only what this environment actually has — an
|
|
105
|
+
# Anthropic-only app must not be forced to install `openai`.
|
|
106
|
+
candidates = (
|
|
107
|
+
("openai", "opentelemetry.instrumentation.openai", "OpenAIInstrumentor"),
|
|
108
|
+
("anthropic", "opentelemetry.instrumentation.anthropic", "AnthropicInstrumentor"),
|
|
109
|
+
(
|
|
110
|
+
"google-generativeai",
|
|
111
|
+
"opentelemetry.instrumentation.google_generativeai",
|
|
112
|
+
"GoogleGenerativeAiInstrumentor",
|
|
113
|
+
),
|
|
114
|
+
("langchain", "opentelemetry.instrumentation.langchain", "LangchainInstrumentor"),
|
|
115
|
+
)
|
|
116
|
+
instrumented: list[str] = []
|
|
117
|
+
import importlib
|
|
118
|
+
|
|
119
|
+
for name, module_path, class_name in candidates:
|
|
120
|
+
try:
|
|
121
|
+
instrumentor = getattr(importlib.import_module(module_path), class_name)()
|
|
122
|
+
except ImportError:
|
|
123
|
+
continue # target library not installed — nothing to trace
|
|
124
|
+
if not instrumentor.is_instrumented_by_opentelemetry:
|
|
125
|
+
instrumentor.instrument(tracer_provider=provider)
|
|
126
|
+
instrumented.append(name)
|
|
127
|
+
|
|
128
|
+
return Tracing(provider, instrumented)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from errorbar_tracing import DEFAULT_ENDPOINT, TAG_ATTRIBUTE, resolve_config
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_refuses_without_api_key():
|
|
7
|
+
with pytest.raises(ValueError, match="ERRORBAR_API_KEY"):
|
|
8
|
+
resolve_config(env={})
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_defaults_to_gateway_with_bearer():
|
|
12
|
+
c = resolve_config(api_key="sk_x", env={})
|
|
13
|
+
assert c.endpoint == DEFAULT_ENDPOINT
|
|
14
|
+
assert c.headers["Authorization"] == "Bearer sk_x"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_reads_env():
|
|
18
|
+
c = resolve_config(
|
|
19
|
+
env={
|
|
20
|
+
"OMNIA_API_KEY": "sk_env",
|
|
21
|
+
"OMNIA_TAG": "checkout-agent",
|
|
22
|
+
"OMNIA_OTLP_ENDPOINT": "https://other.example/v1/traces",
|
|
23
|
+
"OTEL_SERVICE_NAME": "svc",
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
assert c.headers["Authorization"] == "Bearer sk_env"
|
|
27
|
+
assert c.resource_attributes[TAG_ATTRIBUTE] == "checkout-agent"
|
|
28
|
+
assert c.endpoint == "https://other.example/v1/traces"
|
|
29
|
+
assert c.service_name == "svc"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_options_beat_env():
|
|
33
|
+
c = resolve_config(
|
|
34
|
+
api_key="sk_opt",
|
|
35
|
+
tag="t2",
|
|
36
|
+
env={"OMNIA_API_KEY": "sk_env", "OMNIA_TAG": "t1"},
|
|
37
|
+
)
|
|
38
|
+
assert c.headers["Authorization"] == "Bearer sk_opt"
|
|
39
|
+
assert c.resource_attributes[TAG_ATTRIBUTE] == "t2"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_no_tag_means_no_attribute():
|
|
43
|
+
c = resolve_config(api_key="k", env={})
|
|
44
|
+
assert c.resource_attributes == {}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_errorbar_env_names_take_precedence_and_omnia_still_works():
|
|
48
|
+
c = resolve_config(
|
|
49
|
+
env={
|
|
50
|
+
"ERRORBAR_API_KEY": "sk_new",
|
|
51
|
+
"OMNIA_API_KEY": "sk_old",
|
|
52
|
+
"ERRORBAR_TAG": "new-tag",
|
|
53
|
+
"ERRORBAR_OTLP_ENDPOINT": "https://new.example/v1/traces",
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
assert c.headers["Authorization"] == "Bearer sk_new"
|
|
57
|
+
assert c.resource_attributes[TAG_ATTRIBUTE] == "new-tag"
|
|
58
|
+
assert c.endpoint == "https://new.example/v1/traces"
|
|
59
|
+
legacy = resolve_config(env={"OMNIA_API_KEY": "sk_old"})
|
|
60
|
+
assert legacy.headers["Authorization"] == "Bearer sk_old"
|