Coverage for polar/logfire.py: 86%
49 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 12:42 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 12:42 +0000
1import os
2from collections.abc import Callable, Sequence
3from typing import TYPE_CHECKING, Any, Literal
5import httpx
6import logfire
7from fastapi import FastAPI
8from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
9from opentelemetry.sdk.trace.sampling import (
10 ALWAYS_OFF,
11 ALWAYS_ON,
12 ParentBased,
13 Sampler,
14 SamplingResult,
15)
17if TYPE_CHECKING: 17 ↛ 18line 17 didn't jump to line 18 because the condition on line 17 was never true
18 from opentelemetry.context import Context
19 from opentelemetry.trace import Link, SpanKind
20 from opentelemetry.trace.span import TraceState
21 from opentelemetry.util.types import Attributes
23from polar.config import settings
24from polar.kit.db.postgres import Engine
26Matcher = Callable[[str, "Attributes | None"], bool]
29class IgnoreSampler(Sampler):
30 def __init__(self, matchers: Sequence[Matcher]) -> None:
31 super().__init__()
32 self.matchers = matchers
34 def should_sample(
35 self,
36 parent_context: "Context | None",
37 trace_id: int,
38 name: str,
39 kind: "SpanKind | None" = None,
40 attributes: "Attributes | None" = None,
41 links: Sequence["Link"] | None = None,
42 trace_state: "TraceState | None" = None,
43 ) -> SamplingResult:
44 sampler = ALWAYS_ON
46 for matcher in self.matchers:
47 if matcher(name, attributes):
48 sampler = ALWAYS_OFF
49 break
51 return sampler.should_sample(
52 parent_context,
53 trace_id,
54 name,
55 kind,
56 attributes,
57 links,
58 trace_state,
59 )
61 def get_description(self) -> str:
62 return "IgnoreSampler"
65def _healthz_matcher(name: str, attributes: "Attributes | None") -> bool:
66 return attributes is not None and attributes.get("http.route") == "/healthz"
69def _worker_health_matcher(name: str, attributes: "Attributes | None") -> bool:
70 lower_name = name.lower()
71 return lower_name.startswith("recording health:") or lower_name.startswith(
72 "health check successful"
73 )
76def _scrubbing_callback(match: logfire.ScrubMatch) -> Any | None:
77 # Don't scrub auth subject in log messages
78 if match.path == ("attributes", "subject"): 78 ↛ 79line 78 didn't jump to line 79 because the condition on line 78 was never true
79 return match.value
80 return None
83def configure_logfire(service_name: Literal["server", "worker"]) -> None:
84 logfire.configure(
85 send_to_logfire="if-token-present",
86 token=settings.LOGFIRE_TOKEN,
87 service_name=service_name,
88 service_version=os.environ.get("RELEASE_VERSION", "development"),
89 console=False,
90 sampling=logfire.SamplingOptions(
91 head=ParentBased(IgnoreSampler((_healthz_matcher, _worker_health_matcher))),
92 ),
93 scrubbing=logfire.ScrubbingOptions(callback=_scrubbing_callback),
94 )
97def instrument_httpx(client: httpx.AsyncClient | httpx.Client | None = None) -> None:
98 if client:
99 HTTPXClientInstrumentor().instrument_client(client)
100 else:
101 HTTPXClientInstrumentor().instrument()
104def instrument_fastapi(app: FastAPI) -> None:
105 logfire.instrument_fastapi(app, capture_headers=True)
108def instrument_sqlalchemy(engines: Sequence[Engine]) -> None:
109 logfire.instrument_sqlalchemy(engines=engines)
112__all__ = [
113 "configure_logfire",
114 "instrument_fastapi",
115 "instrument_sqlalchemy",
116]