logfire-sdk 6.0.0b2__py3-none-any.whl
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.
- _logfire_sdk/logfire/.agents/skills/logfire-evals/SKILL.md +170 -0
- _logfire_sdk/logfire/.agents/skills/logfire-infrastructure/SKILL.md +61 -0
- _logfire_sdk/logfire/.agents/skills/logfire-infrastructure/references/collector/host-and-infra-metrics.md +229 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/SKILL.md +286 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/auth.md +100 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/ai-sdk.md +145 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/cloudflare-and-deno.md +99 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/frameworks.md +21 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/installation-and-env.md +75 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/nextjs.md +130 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/node-runtime.md +132 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/patterns.md +184 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/project-detection.md +43 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/react-browser.md +90 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/javascript/verification-troubleshooting.md +68 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/python/integrations.md +104 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/python/logging-patterns.md +120 -0
- _logfire_sdk/logfire/.agents/skills/logfire-instrumentation/references/rust/patterns.md +113 -0
- _logfire_sdk/logfire/.agents/skills/logfire-setup/SKILL.md +41 -0
- _logfire_sdk/logfire/.agents/skills/logfire-setup-offline.md +690 -0
- _logfire_sdk/logfire/__init__.py +224 -0
- _logfire_sdk/logfire/__main__.py +6 -0
- _logfire_sdk/logfire/_internal/__init__.py +14 -0
- _logfire_sdk/logfire/_internal/ast_utils.py +264 -0
- _logfire_sdk/logfire/_internal/async_.py +125 -0
- _logfire_sdk/logfire/_internal/auth.py +298 -0
- _logfire_sdk/logfire/_internal/auto_trace/__init__.py +74 -0
- _logfire_sdk/logfire/_internal/auto_trace/import_hook.py +137 -0
- _logfire_sdk/logfire/_internal/auto_trace/rewrite_ast.py +185 -0
- _logfire_sdk/logfire/_internal/auto_trace/types.py +44 -0
- _logfire_sdk/logfire/_internal/baggage.py +109 -0
- _logfire_sdk/logfire/_internal/cli/__init__.py +1065 -0
- _logfire_sdk/logfire/_internal/cli/ai_tools.py +231 -0
- _logfire_sdk/logfire/_internal/cli/auth.py +145 -0
- _logfire_sdk/logfire/_internal/cli/gateway.py +627 -0
- _logfire_sdk/logfire/_internal/cli/gateway_auth.py +313 -0
- _logfire_sdk/logfire/_internal/cli/prompt.py +50 -0
- _logfire_sdk/logfire/_internal/cli/run.py +583 -0
- _logfire_sdk/logfire/_internal/client.py +176 -0
- _logfire_sdk/logfire/_internal/collect_system_info.py +29 -0
- _logfire_sdk/logfire/_internal/config.py +2393 -0
- _logfire_sdk/logfire/_internal/config_params.py +325 -0
- _logfire_sdk/logfire/_internal/constants.py +185 -0
- _logfire_sdk/logfire/_internal/db_statement_summary.py +135 -0
- _logfire_sdk/logfire/_internal/exporters/__init__.py +1 -0
- _logfire_sdk/logfire/_internal/exporters/console.py +513 -0
- _logfire_sdk/logfire/_internal/exporters/dynamic_batch.py +49 -0
- _logfire_sdk/logfire/_internal/exporters/logs.py +30 -0
- _logfire_sdk/logfire/_internal/exporters/otlp.py +401 -0
- _logfire_sdk/logfire/_internal/exporters/processor_wrapper.py +638 -0
- _logfire_sdk/logfire/_internal/exporters/quiet_metrics.py +18 -0
- _logfire_sdk/logfire/_internal/exporters/remove_pending.py +45 -0
- _logfire_sdk/logfire/_internal/exporters/test.py +249 -0
- _logfire_sdk/logfire/_internal/exporters/wrapper.py +106 -0
- _logfire_sdk/logfire/_internal/formatter.py +379 -0
- _logfire_sdk/logfire/_internal/forwarding.py +585 -0
- _logfire_sdk/logfire/_internal/instrument.py +254 -0
- _logfire_sdk/logfire/_internal/integrations/__init__.py +1 -0
- _logfire_sdk/logfire/_internal/integrations/aiohttp_client.py +324 -0
- _logfire_sdk/logfire/_internal/integrations/aiohttp_server.py +22 -0
- _logfire_sdk/logfire/_internal/integrations/asgi.py +117 -0
- _logfire_sdk/logfire/_internal/integrations/asyncpg.py +21 -0
- _logfire_sdk/logfire/_internal/integrations/aws_lambda.py +36 -0
- _logfire_sdk/logfire/_internal/integrations/celery.py +20 -0
- _logfire_sdk/logfire/_internal/integrations/claude_agent_sdk.py +596 -0
- _logfire_sdk/logfire/_internal/integrations/django.py +41 -0
- _logfire_sdk/logfire/_internal/integrations/dspy.py +20 -0
- _logfire_sdk/logfire/_internal/integrations/executors.py +99 -0
- _logfire_sdk/logfire/_internal/integrations/fastapi.py +333 -0
- _logfire_sdk/logfire/_internal/integrations/flask.py +45 -0
- _logfire_sdk/logfire/_internal/integrations/google_genai.py +66 -0
- _logfire_sdk/logfire/_internal/integrations/httpx.py +577 -0
- _logfire_sdk/logfire/_internal/integrations/litellm.py +20 -0
- _logfire_sdk/logfire/_internal/integrations/litestar.py +74 -0
- _logfire_sdk/logfire/_internal/integrations/llm_providers/anthropic.py +400 -0
- _logfire_sdk/logfire/_internal/integrations/llm_providers/llm_provider.py +253 -0
- _logfire_sdk/logfire/_internal/integrations/llm_providers/openai.py +840 -0
- _logfire_sdk/logfire/_internal/integrations/llm_providers/semconv.py +194 -0
- _logfire_sdk/logfire/_internal/integrations/llm_providers/types.py +36 -0
- _logfire_sdk/logfire/_internal/integrations/llm_providers/usage.py +82 -0
- _logfire_sdk/logfire/_internal/integrations/mcp.py +173 -0
- _logfire_sdk/logfire/_internal/integrations/mysql.py +34 -0
- _logfire_sdk/logfire/_internal/integrations/openai_agents.py +454 -0
- _logfire_sdk/logfire/_internal/integrations/print.py +176 -0
- _logfire_sdk/logfire/_internal/integrations/psycopg.py +126 -0
- _logfire_sdk/logfire/_internal/integrations/pydantic_ai.py +65 -0
- _logfire_sdk/logfire/_internal/integrations/pymongo.py +40 -0
- _logfire_sdk/logfire/_internal/integrations/pytest.py +648 -0
- _logfire_sdk/logfire/_internal/integrations/redis.py +57 -0
- _logfire_sdk/logfire/_internal/integrations/requests.py +34 -0
- _logfire_sdk/logfire/_internal/integrations/snowflake.py +162 -0
- _logfire_sdk/logfire/_internal/integrations/sqlalchemy.py +50 -0
- _logfire_sdk/logfire/_internal/integrations/sqlite3.py +29 -0
- _logfire_sdk/logfire/_internal/integrations/starlette.py +48 -0
- _logfire_sdk/logfire/_internal/integrations/surrealdb.py +137 -0
- _logfire_sdk/logfire/_internal/integrations/system_metrics.py +322 -0
- _logfire_sdk/logfire/_internal/integrations/wsgi.py +34 -0
- _logfire_sdk/logfire/_internal/interactive.py +115 -0
- _logfire_sdk/logfire/_internal/json_encoder.py +346 -0
- _logfire_sdk/logfire/_internal/json_formatter.py +325 -0
- _logfire_sdk/logfire/_internal/json_schema.py +451 -0
- _logfire_sdk/logfire/_internal/json_types.py +145 -0
- _logfire_sdk/logfire/_internal/logs.py +129 -0
- _logfire_sdk/logfire/_internal/main.py +3471 -0
- _logfire_sdk/logfire/_internal/metrics.py +280 -0
- _logfire_sdk/logfire/_internal/scrubbing.py +400 -0
- _logfire_sdk/logfire/_internal/server_response.py +44 -0
- _logfire_sdk/logfire/_internal/stack_info.py +147 -0
- _logfire_sdk/logfire/_internal/tracer.py +509 -0
- _logfire_sdk/logfire/_internal/ulid.py +40 -0
- _logfire_sdk/logfire/_internal/utils.py +550 -0
- _logfire_sdk/logfire/cli.py +3 -0
- _logfire_sdk/logfire/db_api.py +393 -0
- _logfire_sdk/logfire/exceptions.py +9 -0
- _logfire_sdk/logfire/experimental/__init__.py +0 -0
- _logfire_sdk/logfire/experimental/annotations.py +80 -0
- _logfire_sdk/logfire/experimental/api_client.py +1419 -0
- _logfire_sdk/logfire/integrations/__init__.py +4 -0
- _logfire_sdk/logfire/integrations/aiohttp_client.py +12 -0
- _logfire_sdk/logfire/integrations/flask.py +26 -0
- _logfire_sdk/logfire/integrations/httpx.py +49 -0
- _logfire_sdk/logfire/integrations/logging.py +148 -0
- _logfire_sdk/logfire/integrations/loguru.py +98 -0
- _logfire_sdk/logfire/integrations/psycopg.py +23 -0
- _logfire_sdk/logfire/integrations/pydantic.py +541 -0
- _logfire_sdk/logfire/integrations/redis.py +31 -0
- _logfire_sdk/logfire/integrations/sqlalchemy.py +12 -0
- _logfire_sdk/logfire/integrations/structlog.py +51 -0
- _logfire_sdk/logfire/integrations/wsgi.py +15 -0
- _logfire_sdk/logfire/propagate.py +161 -0
- _logfire_sdk/logfire/py.typed +0 -0
- _logfire_sdk/logfire/query_client.py +598 -0
- _logfire_sdk/logfire/sampling/__init__.py +9 -0
- _logfire_sdk/logfire/sampling/_tail_sampling.py +292 -0
- _logfire_sdk/logfire/testing.py +127 -0
- _logfire_sdk/logfire/types.py +303 -0
- _logfire_sdk/logfire/variables/__init__.py +154 -0
- _logfire_sdk/logfire/variables/_handlebars.py +77 -0
- _logfire_sdk/logfire/variables/abstract.py +2027 -0
- _logfire_sdk/logfire/variables/composition.py +430 -0
- _logfire_sdk/logfire/variables/config.py +694 -0
- _logfire_sdk/logfire/variables/local.py +134 -0
- _logfire_sdk/logfire/variables/remote.py +864 -0
- _logfire_sdk/logfire/variables/template_validation.py +208 -0
- _logfire_sdk/logfire/variables/variable.py +1299 -0
- _logfire_sdk/logfire/version.py +5 -0
- logfire/.agents/skills/logfire-evals/SKILL.md +170 -0
- logfire/.agents/skills/logfire-infrastructure/SKILL.md +61 -0
- logfire/.agents/skills/logfire-infrastructure/references/collector/host-and-infra-metrics.md +229 -0
- logfire/.agents/skills/logfire-instrumentation/SKILL.md +286 -0
- logfire/.agents/skills/logfire-instrumentation/references/auth.md +100 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/ai-sdk.md +145 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/cloudflare-and-deno.md +99 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/frameworks.md +21 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/installation-and-env.md +75 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/nextjs.md +130 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/node-runtime.md +132 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/patterns.md +184 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/project-detection.md +43 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/react-browser.md +90 -0
- logfire/.agents/skills/logfire-instrumentation/references/javascript/verification-troubleshooting.md +68 -0
- logfire/.agents/skills/logfire-instrumentation/references/python/integrations.md +104 -0
- logfire/.agents/skills/logfire-instrumentation/references/python/logging-patterns.md +120 -0
- logfire/.agents/skills/logfire-instrumentation/references/rust/patterns.md +113 -0
- logfire/.agents/skills/logfire-setup/SKILL.md +41 -0
- logfire/.agents/skills/logfire-setup-offline.md +690 -0
- logfire/__init__.py +224 -0
- logfire/__main__.py +6 -0
- logfire/_internal/__init__.py +14 -0
- logfire/_internal/ast_utils.py +264 -0
- logfire/_internal/async_.py +125 -0
- logfire/_internal/auth.py +298 -0
- logfire/_internal/auto_trace/__init__.py +74 -0
- logfire/_internal/auto_trace/import_hook.py +137 -0
- logfire/_internal/auto_trace/rewrite_ast.py +185 -0
- logfire/_internal/auto_trace/types.py +44 -0
- logfire/_internal/baggage.py +109 -0
- logfire/_internal/cli/__init__.py +1065 -0
- logfire/_internal/cli/ai_tools.py +231 -0
- logfire/_internal/cli/auth.py +145 -0
- logfire/_internal/cli/gateway.py +627 -0
- logfire/_internal/cli/gateway_auth.py +313 -0
- logfire/_internal/cli/prompt.py +50 -0
- logfire/_internal/cli/run.py +583 -0
- logfire/_internal/client.py +176 -0
- logfire/_internal/collect_system_info.py +29 -0
- logfire/_internal/config.py +2393 -0
- logfire/_internal/config_params.py +325 -0
- logfire/_internal/constants.py +185 -0
- logfire/_internal/db_statement_summary.py +135 -0
- logfire/_internal/exporters/__init__.py +1 -0
- logfire/_internal/exporters/console.py +513 -0
- logfire/_internal/exporters/dynamic_batch.py +49 -0
- logfire/_internal/exporters/logs.py +30 -0
- logfire/_internal/exporters/otlp.py +401 -0
- logfire/_internal/exporters/processor_wrapper.py +638 -0
- logfire/_internal/exporters/quiet_metrics.py +18 -0
- logfire/_internal/exporters/remove_pending.py +45 -0
- logfire/_internal/exporters/test.py +249 -0
- logfire/_internal/exporters/wrapper.py +106 -0
- logfire/_internal/formatter.py +379 -0
- logfire/_internal/forwarding.py +585 -0
- logfire/_internal/instrument.py +254 -0
- logfire/_internal/integrations/__init__.py +1 -0
- logfire/_internal/integrations/aiohttp_client.py +324 -0
- logfire/_internal/integrations/aiohttp_server.py +22 -0
- logfire/_internal/integrations/asgi.py +117 -0
- logfire/_internal/integrations/asyncpg.py +21 -0
- logfire/_internal/integrations/aws_lambda.py +36 -0
- logfire/_internal/integrations/celery.py +20 -0
- logfire/_internal/integrations/claude_agent_sdk.py +596 -0
- logfire/_internal/integrations/django.py +41 -0
- logfire/_internal/integrations/dspy.py +20 -0
- logfire/_internal/integrations/executors.py +99 -0
- logfire/_internal/integrations/fastapi.py +333 -0
- logfire/_internal/integrations/flask.py +45 -0
- logfire/_internal/integrations/google_genai.py +66 -0
- logfire/_internal/integrations/httpx.py +577 -0
- logfire/_internal/integrations/litellm.py +20 -0
- logfire/_internal/integrations/litestar.py +74 -0
- logfire/_internal/integrations/llm_providers/anthropic.py +400 -0
- logfire/_internal/integrations/llm_providers/llm_provider.py +253 -0
- logfire/_internal/integrations/llm_providers/openai.py +840 -0
- logfire/_internal/integrations/llm_providers/semconv.py +194 -0
- logfire/_internal/integrations/llm_providers/types.py +36 -0
- logfire/_internal/integrations/llm_providers/usage.py +82 -0
- logfire/_internal/integrations/mcp.py +173 -0
- logfire/_internal/integrations/mysql.py +34 -0
- logfire/_internal/integrations/openai_agents.py +454 -0
- logfire/_internal/integrations/print.py +176 -0
- logfire/_internal/integrations/psycopg.py +126 -0
- logfire/_internal/integrations/pydantic_ai.py +65 -0
- logfire/_internal/integrations/pymongo.py +40 -0
- logfire/_internal/integrations/pytest.py +648 -0
- logfire/_internal/integrations/redis.py +57 -0
- logfire/_internal/integrations/requests.py +34 -0
- logfire/_internal/integrations/snowflake.py +162 -0
- logfire/_internal/integrations/sqlalchemy.py +50 -0
- logfire/_internal/integrations/sqlite3.py +29 -0
- logfire/_internal/integrations/starlette.py +48 -0
- logfire/_internal/integrations/surrealdb.py +137 -0
- logfire/_internal/integrations/system_metrics.py +322 -0
- logfire/_internal/integrations/wsgi.py +34 -0
- logfire/_internal/interactive.py +115 -0
- logfire/_internal/json_encoder.py +346 -0
- logfire/_internal/json_formatter.py +325 -0
- logfire/_internal/json_schema.py +451 -0
- logfire/_internal/json_types.py +145 -0
- logfire/_internal/logs.py +129 -0
- logfire/_internal/main.py +3471 -0
- logfire/_internal/metrics.py +280 -0
- logfire/_internal/scrubbing.py +400 -0
- logfire/_internal/server_response.py +44 -0
- logfire/_internal/stack_info.py +147 -0
- logfire/_internal/tracer.py +509 -0
- logfire/_internal/ulid.py +40 -0
- logfire/_internal/utils.py +550 -0
- logfire/cli.py +3 -0
- logfire/db_api.py +393 -0
- logfire/exceptions.py +9 -0
- logfire/experimental/__init__.py +0 -0
- logfire/experimental/annotations.py +80 -0
- logfire/experimental/api_client.py +1419 -0
- logfire/integrations/__init__.py +4 -0
- logfire/integrations/aiohttp_client.py +12 -0
- logfire/integrations/flask.py +26 -0
- logfire/integrations/httpx.py +49 -0
- logfire/integrations/logging.py +148 -0
- logfire/integrations/loguru.py +98 -0
- logfire/integrations/psycopg.py +23 -0
- logfire/integrations/pydantic.py +541 -0
- logfire/integrations/redis.py +31 -0
- logfire/integrations/sqlalchemy.py +12 -0
- logfire/integrations/structlog.py +51 -0
- logfire/integrations/wsgi.py +15 -0
- logfire/propagate.py +161 -0
- logfire/py.typed +0 -0
- logfire/query_client.py +598 -0
- logfire/sampling/__init__.py +9 -0
- logfire/sampling/_tail_sampling.py +292 -0
- logfire/testing.py +127 -0
- logfire/types.py +303 -0
- logfire/variables/__init__.py +154 -0
- logfire/variables/_handlebars.py +77 -0
- logfire/variables/abstract.py +2027 -0
- logfire/variables/composition.py +430 -0
- logfire/variables/config.py +694 -0
- logfire/variables/local.py +134 -0
- logfire/variables/remote.py +864 -0
- logfire/variables/template_validation.py +208 -0
- logfire/variables/variable.py +1299 -0
- logfire/version.py +5 -0
- logfire_sdk-6.0.0b2.dist-info/METADATA +137 -0
- logfire_sdk-6.0.0b2.dist-info/RECORD +298 -0
- logfire_sdk-6.0.0b2.dist-info/WHEEL +4 -0
- logfire_sdk-6.0.0b2.dist-info/entry_points.txt +6 -0
- logfire_sdk-6.0.0b2.dist-info/licenses/LICENSE +21 -0
- logfire_sdk.pth +2 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: logfire-evals
|
|
3
|
+
description: Run offline Python (`pydantic_evals`) or Node.js (`logfire/evals`) evaluations and review them in Logfire. Also redirect existing Braintrust `Eval()` suites. Use for eval setup, test datasets, AI scoring, agent checks, LLM judges, Braintrust migration, or Logfire Datasets & Experiments. Not for live traffic or infrastructure monitoring.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Evaluate AI code with Logfire
|
|
7
|
+
|
|
8
|
+
## How This Works
|
|
9
|
+
|
|
10
|
+
Python's `pydantic_evals` and Node.js's `logfire/evals` run a task against cases, apply evaluators, and return a report. An active Logfire or OpenTelemetry provider may export inputs and outputs even if this skill did not configure it. Intentional upload needs `logfire.configure()` in Python or a configured Node.js exporter.
|
|
11
|
+
|
|
12
|
+
Span-based evaluators inspect the task's OpenTelemetry span tree. Without working Logfire instrumentation, Python reports "No span tree available"; Node.js `HasMatchingSpan` can produce no evaluator result at all. Treat either signal as a setup failure, not evidence about the agent.
|
|
13
|
+
|
|
14
|
+
## Step 1: Check for an Existing Braintrust Suite First
|
|
15
|
+
|
|
16
|
+
Cheap check, before anything else: does this repo already have an existing Braintrust suite — actual `Eval(...)` calls or `from braintrust import Eval` in source, not just a `braintrust` dependency listed without any real usage? This path needs **no CLI auth at all** — don't run Step 2 for it. The compatibility endpoint is documented only for Logfire Cloud US and EU; for any other supplied origin, use the native evaluation path instead.
|
|
17
|
+
|
|
18
|
+
Keep the existing `Eval()` code (Python `braintrust>=0.30.1` / TypeScript `braintrust>=3.24.0` — verified versions) and redirect its next run to Logfire by changing environment variables only, no `pydantic_evals` involved:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
export BRAINTRUST_APP_URL="https://logfire-us.pydantic.dev/v1/braintrust" # EU: logfire-eu.pydantic.dev
|
|
22
|
+
export BRAINTRUST_API_KEY="<logfire-project-api-key>" # Settings -> API Keys
|
|
23
|
+
unset BRAINTRUST_API_URL BRAINTRUST_PROXY_URL # these override the endpoint above if set — the #1 "it still hit Braintrust" cause
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The destination project's API key needs `project:write_otlp` and `project:read_datasets`: the SDK writes the run, then reads experiment metadata for its summary. An ingest-only write token fails with `403`.
|
|
27
|
+
|
|
28
|
+
This **compatibility preview** covers inline/callable data, local tasks and scorers, multiple scores, one label per name, and normal summary finalization. It excludes Braintrust-hosted resources, BTQL, the model proxy, server-side scoring, and post-finalization feedback. Rust, `summarize_scores=False`, and manual `flush()` without comparison do not request the summary needed for projection. See the [full coverage and concept mapping](https://pydantic.dev/docs/logfire/get-started/comparisons/migrate-from-braintrust/).
|
|
29
|
+
|
|
30
|
+
Skip straight to Step 5 (Verify) — the SDK's own printed result URL also opens directly in Logfire, and nothing else here (auth, dataset definition) applies to this path.
|
|
31
|
+
|
|
32
|
+
**No existing Braintrust suite? Continue to Step 2 now**, before the more detailed identification in Step 3 — nothing past this point requires knowing the function/agent or dataset shape yet.
|
|
33
|
+
|
|
34
|
+
## Step 2: Authenticate When the Run Needs Logfire
|
|
35
|
+
|
|
36
|
+
For an explicitly local-only run without span evaluators, use a fresh process that neither preloads nor imports application telemetry; omit Python's `logfire.configure()` and any Node.js exporter bootstrap. If the task configures an exporter and has no documented disable switch, stop rather than claiming local-only. Uploading, hosted datasets, and span evaluators require Logfire authentication to the exact project.
|
|
37
|
+
|
|
38
|
+
For a Logfire-backed run, use [Authenticate and Select the Exact Project](https://pydantic.dev/.well-known/agent-skills/logfire-instrumentation/references/auth.md) to derive the CLI target from the supplied Logfire URL and run its target-aware `whoami` check with a verified CLI path — for JS/TS projects without `uv`, use the external-prefix npm fallback instead of plain `npx`, which can execute a repository-local binary. Skip to Step 3 if that already reports the right project and resolved `--region` or `--base-url` target; otherwise, continue through the full authentication and project-selection sequence there. This CLI flow is for `logfire.configure()`; Step 3's hosted-dataset operations use a separate API key with different scopes.
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## Step 3: Detect What to Evaluate
|
|
42
|
+
|
|
43
|
+
Identify the real task and any dataset. Follow repository package, test, and dependency conventions. For a first eval, prefer 3-5 cases from tests, schemas, examples, or synthetic fixtures, with deterministic checks for defined behavior. Do not copy the example unless it fits, replace an eval framework, or refactor unrelated code. Without a runnable task or safe expected behavior, ask one focused question instead of inventing either.
|
|
44
|
+
|
|
45
|
+
- **In-code dataset**: a Python module using `pydantic_evals`, or a Node.js module using `logfire/evals`. This is the default for an agent-driven workflow.
|
|
46
|
+
- **Hosted/managed dataset**: cases live in the Logfire UI, edited by non-engineers, pulled/pushed via a separate `LogfireAPIClient` (`from logfire.experimental.api_client import LogfireAPIClient`). Hosted inputs and outputs must be JSON objects; scalar roots accepted by code-defined datasets are rejected. `client.get_dataset(name)` with no type arguments returns a raw dict, not something `push_dataset` or `.evaluate_sync()` can take — pass the input/output (and metadata, if used) types to get back a real `pydantic_evals.Dataset`: `client.get_dataset(name, MyInputType, MyOutputType)`. If the stored dataset contains custom evaluators, also pass their classes with `custom_evaluator_types=[MyEvaluator]` (and custom report evaluators with `custom_report_evaluator_types=[...]`) so they can be deserialized. Push with `client.push_dataset(dataset)`. This needs its own API key from **Settings → API Keys** (scoped `project:read_datasets`/`project:write_datasets`), not Step 2's CLI auth flow. Only relevant if the user specifically wants case editing outside code.
|
|
47
|
+
|
|
48
|
+
## Step 4: Define the Dataset and Run It
|
|
49
|
+
|
|
50
|
+
Use the repository's existing package manager and lockfile. Install only the missing integration for its language.
|
|
51
|
+
|
|
52
|
+
### Python
|
|
53
|
+
|
|
54
|
+
Add `pydantic-evals[logfire]` with the detected Python manager: `uv add`, `poetry add`, or `pdm add`. For a pip/requirements project, update its declared requirements and install from that file; do not introduce a second manager or lockfile.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import logfire
|
|
58
|
+
from pydantic_evals import Case, Dataset
|
|
59
|
+
from pydantic_evals.evaluators import EqualsExpected, IsInstance
|
|
60
|
+
|
|
61
|
+
logfire.configure() # omit only in the isolated local-only process described above
|
|
62
|
+
|
|
63
|
+
def classify_sentiment(text: str) -> str:
|
|
64
|
+
return 'positive' if 'love' in text else 'negative'
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
dataset = Dataset[str, str, None](
|
|
68
|
+
name='sentiment-eval',
|
|
69
|
+
cases=[
|
|
70
|
+
Case(name='positive', inputs='I love this', expected_output='positive'),
|
|
71
|
+
Case(name='negative', inputs='This is terrible', expected_output='negative'),
|
|
72
|
+
],
|
|
73
|
+
evaluators=[EqualsExpected(), IsInstance(type_name='str')],
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
report = dataset.evaluate_sync(classify_sentiment) # or `await dataset.evaluate(...)`
|
|
77
|
+
report.print(include_input=True, include_output=True)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use `logfire[datasets]` instead only when the task specifically needs the hosted-dataset API from Step 3.
|
|
81
|
+
|
|
82
|
+
### JavaScript or TypeScript on Node.js
|
|
83
|
+
|
|
84
|
+
Do not apply this section to Deno, Bun, browsers, or workers; their exporter setup is not validated by this skill.
|
|
85
|
+
|
|
86
|
+
Add `logfire` and `@pydantic/logfire-node` with the manager selected by the existing lockfile: `pnpm add`, `yarn add`, `bun add`, or `npm install`. Do not introduce a second lockfile.
|
|
87
|
+
|
|
88
|
+
Configure Logfire before loading the task. Reuse an existing instrumentation entry point rather than configuring it twice.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import * as logfire from '@pydantic/logfire-node'
|
|
92
|
+
import { Case, Dataset, EqualsExpected, renderReport } from 'logfire/evals'
|
|
93
|
+
|
|
94
|
+
logfire.configure()
|
|
95
|
+
|
|
96
|
+
const classifySentiment = (text: string) => (text.includes('love') ? 'positive' : 'negative')
|
|
97
|
+
const dataset = new Dataset<string, string>({
|
|
98
|
+
name: 'sentiment-eval',
|
|
99
|
+
cases: [new Case({ name: 'positive', inputs: 'I love this', expectedOutput: 'positive' })],
|
|
100
|
+
evaluators: [new EqualsExpected()],
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
await dataset.evaluate(classifySentiment).then((report) => {
|
|
104
|
+
console.log(renderReport(report, { includeInput: true, includeOutput: true }))
|
|
105
|
+
}).finally(() => logfire.shutdown({ timeoutMillis: 5000 }))
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Other built-ins include `Equals`, `Contains`, `IsInstance`, `MaxDuration`, `HasMatchingSpan`, and `LLMJudge`. Node.js custom evaluators extend `Evaluator`, and `LLMJudge` needs a judge callback. Use `@pydantic/logfire-node/datasets` only for hosted datasets.
|
|
109
|
+
|
|
110
|
+
### Smoke test before a paid or full run
|
|
111
|
+
|
|
112
|
+
**Before running the full dataset, run a smoke test on 2-3 cases** if the dataset is large or uses `LLMJudge` or any evaluator that makes billed model calls. This catches setup errors before they multiply cost across the dataset.
|
|
113
|
+
|
|
114
|
+
Python:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
smoke = Dataset(
|
|
118
|
+
name=dataset.name,
|
|
119
|
+
cases=dataset.cases[:3],
|
|
120
|
+
evaluators=dataset.evaluators,
|
|
121
|
+
report_evaluators=dataset.report_evaluators,
|
|
122
|
+
)
|
|
123
|
+
smoke_report = smoke.evaluate_sync(classify_sentiment)
|
|
124
|
+
smoke_report.print(include_input=True, include_output=True)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Node.js:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
const smoke = new Dataset({
|
|
131
|
+
name: dataset.name,
|
|
132
|
+
cases: dataset.cases.slice(0, 3),
|
|
133
|
+
evaluators: dataset.evaluators,
|
|
134
|
+
reportEvaluators: dataset.reportEvaluators,
|
|
135
|
+
})
|
|
136
|
+
await smoke.evaluate(classifySentiment).then((report) => {
|
|
137
|
+
console.log(renderReport(report, { includeInput: true, includeOutput: true }))
|
|
138
|
+
}).finally(() => logfire.shutdown({ timeoutMillis: 5000 }))
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Confirm the smoke run has zero unexpected errors and the assertions that should pass do. Then, if the full dataset is large or uses paid model calls, tell the user the case count and which evaluators will make model calls, and get explicit confirmation before running the full dataset — don't run an expensive full pass on the strength of a clean smoke test alone without saying so.
|
|
142
|
+
|
|
143
|
+
The remaining details in this section are Python-specific. Custom evaluators inherit `Evaluator` and implement `evaluate`; use `@dataclass` for configurable fields and portable serialization. Case names must be unique within a dataset. The evaluators reached for most:
|
|
144
|
+
|
|
145
|
+
| Evaluator | Checks |
|
|
146
|
+
|-----------|--------|
|
|
147
|
+
| `Equals(value)` / `EqualsExpected()` | Exact match against a literal / `expected_output` (no-op if `expected_output` is unset — don't rely on it silently catching that) |
|
|
148
|
+
| `IsInstance(type_name)` | Output's type matches by name |
|
|
149
|
+
| `LLMJudge(rubric, model=None, score=False)` | Subjective or rubric-based judgment; makes billed model requests, so validate the rubric against human-reviewed examples before treating it as a quality gate |
|
|
150
|
+
| `ToolCorrectness(expected_tools, ...)` | Which tools an agent called — reads the span tree, so needs Step 2's `logfire.configure()` to work at all, not just to upload |
|
|
151
|
+
|
|
152
|
+
Also available: `Contains`, `MaxDuration`, `TrajectoryMatch`, `ArgumentCorrectness`, `MaxToolCalls`, `MaxModelRequests` — same span-tree dependency as `ToolCorrectness` for the tool/trajectory ones; see `pydantic_evals.evaluators` for the full set. These five agentic (span-based) evaluators need `pydantic-evals>=2.4.0` — on an older pin, check `pyproject.toml`/`uv.lock` and upgrade before reaching for them, since the import itself is what fails, not a silent no-op.
|
|
153
|
+
|
|
154
|
+
The `Python` evaluator (arbitrary code execution) was removed for security reasons — don't reach for it even if an older example references it.
|
|
155
|
+
|
|
156
|
+
If editing a hosted dataset: `client.push_dataset(dataset)` **overwrites** server-side evaluators on every push, including removing ones you deleted locally — don't push a stale local copy over a dataset others have edited in the UI.
|
|
157
|
+
|
|
158
|
+
## Step 5: Verify
|
|
159
|
+
|
|
160
|
+
A report printing to the terminal isn't proof it reached Logfire — confirm the run actually landed. **Never report a case as passed, a score, or a run as complete without having actually checked it in this session** — if a run fails, cancels, or produces no scores, report that failure plainly; never substitute an invented score or a manual guess at what the result "should" be.
|
|
161
|
+
|
|
162
|
+
**Came from the Step 1 Braintrust path (Step 2 skipped)?** There's no `whoami`-resolved project to look up here — use the SDK's own printed result URL instead, which already opens directly in the right Logfire project. Confirm the same things below (completion, pass mix, case detail) from that page rather than searching by name.
|
|
163
|
+
|
|
164
|
+
1. **Query for the run directly, if a Logfire MCP server or API is connected** — the root span for a run is named `evaluate {name}` and carries `gen_ai.operation.name = 'experiment'`, `dataset_name`, and `task_name` attributes; find the most recent one matching your dataset's name and confirm `logfire.experiment.metadata` shows the case count and pass rate you expect. Otherwise, open **AI Evaluations → Datasets & Experiments → Experiments** in Logfire for the exact project from Step 2, and find the run by name/timestamp.
|
|
165
|
+
2. **Read the Overview tab (or the queried metadata) first**: completion count, assertion pass mix, task errors, average duration. **If completion says "Not reported,"** the run sent case data but never signaled it finished — treat that as a broken run, not a passing one.
|
|
166
|
+
3. **Open the Cases tab**, starting from Needs Review / Failed / Errors, not the full list.
|
|
167
|
+
4. **Drill into a failing case's trace in Live view** for the actual evidence, rather than trusting the summary score alone.
|
|
168
|
+
5. **Fix and re-run** until the cases that should pass do, and any tool-call/trajectory checks show real span data, not "No span tree available."
|
|
169
|
+
|
|
170
|
+
Close with a final report built from what you just confirmed — the run name, exact case count and pass rate you queried, and which evaluators ran — not a template. **Include the direct link to this experiment** (the SDK's own printed result URL, or the Datasets & Experiments page you opened it from), so the user can see the run without having to ask where to look.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: logfire-infrastructure
|
|
3
|
+
description: Monitor hosts, Docker containers, Kubernetes clusters, database/queue/cache servers, and cloud-provider metrics with Pydantic Logfire — no application code required. Use this skill whenever the user asks to "monitor my host/server/VM", "monitor my Docker containers", "monitor my Kubernetes cluster", "send infrastructure metrics to Logfire", "watch my database/Postgres/Redis/MongoDB/Kafka", "collect cloud metrics" (AWS/GCP), or mentions the OpenTelemetry Collector in the context of Logfire. This is infrastructure only — for instrumenting APPLICATION CODE (traces, logs, AI/agent spans) use the logfire-instrumentation skill instead.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Monitor Infrastructure with Logfire
|
|
7
|
+
|
|
8
|
+
Do **not** use this skill for application-level traces, logs, or AI/agent spans — that's `logfire-instrumentation`. The two compose: a full setup often runs both.
|
|
9
|
+
|
|
10
|
+
## How This Works
|
|
11
|
+
|
|
12
|
+
The OpenTelemetry Collector ships host, container, cluster, and infrastructure-service metrics to Logfire with **no application code changes** — Logfire is a fully compliant OTel backend and ingests standard OTLP traces, logs, and metrics from it (one narrow exception noted in the [collector reference](./references/collector/host-and-infra-metrics.md)), so the Collector is the entire mechanism. This is optional and is an advanced tool: if the user only wants their app's own traces, `logfire-instrumentation`'s language SDKs are enough on their own.
|
|
13
|
+
|
|
14
|
+
## Step 1: Authenticate and Select the Exact Project
|
|
15
|
+
|
|
16
|
+
Do not open, read, or run any infrastructure config file (`docker-compose.yml`, a Kubernetes manifest, or similar) until `whoami` confirms you're authenticated to the right project — nothing about this step requires knowing what's being monitored. Auth is also the one step that can block on a human (browser sign-in), so starting it first means that wait begins on turn one, not after Step 2's detection work.
|
|
17
|
+
|
|
18
|
+
Use [Authenticate and Select the Exact Project](https://pydantic.dev/.well-known/agent-skills/logfire-instrumentation/references/auth.md) to derive the CLI target from the supplied Logfire URL and run its target-aware `whoami` check with a verified CLI path — for JS/TS projects without `uv`, use the external-prefix npm fallback instead of plain `npx`, which can execute a repository-local binary. Skip to Step 2 if that already reports the right project and resolved `--region` or `--base-url` target; otherwise, continue through the full authentication and project-selection sequence there, including its safe handoff for the write credential created by `projects use`.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## Step 2: Identify What to Monitor
|
|
22
|
+
|
|
23
|
+
Detect the infrastructure actually in play, don't assume:
|
|
24
|
+
|
|
25
|
+
- **Host/VM**: monitoring the machine itself (CPU, memory, disk, network, load).
|
|
26
|
+
- **Docker**: read `docker-compose.yml` / `Dockerfile`s for running containers.
|
|
27
|
+
- **Kubernetes**: look for manifests, a `kubeconfig`, or `kubectl` context.
|
|
28
|
+
- **Database/queue/cache servers**: read `docker-compose.yml` / `pyproject.toml` / `package.json` for Postgres, MySQL, Redis, MongoDB, Kafka, RabbitMQ, Nginx, Apache, Elasticsearch, or Memcached.
|
|
29
|
+
- **Cloud provider**: GCP or AWS metrics (Cloud Monitoring, CloudWatch, ECS), when the user names the provider or the app clearly runs there.
|
|
30
|
+
|
|
31
|
+
More than one can apply at once — a single Collector can run multiple receivers in parallel pipelines.
|
|
32
|
+
|
|
33
|
+
## Step 3: Configure the Collector
|
|
34
|
+
|
|
35
|
+
Follow the [collector reference](./references/collector/host-and-infra-metrics.md) for the receiver(s) identified in Step 2 — it covers the shared exporter setup, then a dedicated section per source: host metrics, Docker, Kubernetes, database/queue/cache servers, and cloud-provider metrics, each with the exact receiver name, a working config, and the caveats that actually bite (Docker socket permissions, API version pinning, `host.docker.internal` vs `localhost`, IAM permissions, ADOT vs. Contrib collector images).
|
|
36
|
+
|
|
37
|
+
Set the same service & resource metadata conventions the [collector reference](./references/collector/host-and-infra-metrics.md) describes — `host.name`, `service.name`, `service.instance.id` — so data groups correctly across the Hosts, Kubernetes, and Metrics pages.
|
|
38
|
+
|
|
39
|
+
Before starting or restarting the Collector, validate the config file — a receiver typo or bad indentation should surface as a validation error, not a Collector that starts, logs nothing useful, and silently drops the pipeline:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
otelcol-contrib validate --config=collector-config.yaml
|
|
43
|
+
# or, for the core (non-Contrib) distribution: otelcol validate --config=...
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If neither binary is on `PATH`, inspect the running Collector container (for example with `kubectl exec`) or use the deployment-specific validation command from the image entrypoint, systemd unit, or Helm chart. `docker compose config` or `kubectl get pod <name> -o yaml` can show the command when it is explicitly configured.
|
|
47
|
+
|
|
48
|
+
## Step 4: Verify
|
|
49
|
+
|
|
50
|
+
Wiring a receiver isn't done when the Collector starts cleanly — confirm the data actually reached the right page for the right host/container/cluster, not just that something arrived. **Never report a metric as "arrived" without having queried for it in this same session** — a plausible-sounding summary that wasn't checked is worse than saying you couldn't verify.
|
|
51
|
+
|
|
52
|
+
1. **Restart the Collector** after any config change (having validated it, above).
|
|
53
|
+
2. **Query for the exact resource you configured, not just any data on the page.** If a Logfire MCP server or API is connected in this session, query for the specific `host.name` / container / cluster you set in Step 3 within the last few minutes — a query that returns zero rows for that exact identifier means it didn't land, even if the page shows data from something else. Otherwise, open the specific product page — **Hosts**, **Docker**, or **Kubernetes** — or the **Metrics** explorer for database/queue/cache/cloud sources, and look for that same exact identifier.
|
|
54
|
+
3. **If nothing appears**, check in order: the exporter endpoint/region and write token, that the receiver is in an active pipeline (not defined but never referenced under `service.pipelines`), and that resource attributes (`host.name`, `service.name`) are set — the [reference's own Verify section](./references/collector/host-and-infra-metrics.md) has the full troubleshooting path.
|
|
55
|
+
4. **Fix and re-check** until the specific source is visible, not just "some" data.
|
|
56
|
+
|
|
57
|
+
Close with a final report built from what you just confirmed — org/project/region from `whoami`, which receiver(s) are active, and the exact host/container/cluster identifier you verified — not a template. **Include a direct link to the relevant view** (`/hosts`, `/docker`, `/kubernetes`, or `/metrics`, based on the source) using the project's URL from `whoami`, so the user can see their own source arrive without having to ask where to look. A report with a placeholder in it means a step above was skipped, not finished.
|
|
58
|
+
|
|
59
|
+
## References
|
|
60
|
+
|
|
61
|
+
- [Host, Docker, Kubernetes, database/queue/cache, and cloud-provider metrics via the OTel Collector](./references/collector/host-and-infra-metrics.md) — receiver configs, IAM/permission caveats, and its own verify loop.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Host & Infrastructure Metrics (OpenTelemetry Collector)
|
|
2
|
+
|
|
3
|
+
A large share of useful telemetry — host CPU/memory/disk, Kubernetes cluster
|
|
4
|
+
state, and metrics from database/queue/cache servers — comes from
|
|
5
|
+
**infrastructure**, not application code. The OpenTelemetry Collector collects
|
|
6
|
+
these and ships them to Logfire over OTLP, with no changes to your app. Logfire
|
|
7
|
+
is a fully compliant OpenTelemetry backend and ingests OTLP traces, logs, and
|
|
8
|
+
metrics from the Collector — with one metric-type exception: the legacy OTLP
|
|
9
|
+
`Summary` type (superseded by histograms in the OTel spec) is not ingested. If
|
|
10
|
+
a receiver's metrics don't show up and its docs say it emits `Summary` points,
|
|
11
|
+
that's why — look for a histogram- or gauge-producing alternative.
|
|
12
|
+
|
|
13
|
+
Reach for this path whenever the user wants "as much useful data as would be
|
|
14
|
+
useful," is monitoring a host/VM/cluster, or wants a database/queue/cache server
|
|
15
|
+
watched. App instrumentation alone never produces this data.
|
|
16
|
+
|
|
17
|
+
> The Collector is optional and is an advanced tool. If the user only wants their
|
|
18
|
+
> app's own traces, the language SDKs (covered in the main skill) are enough.
|
|
19
|
+
|
|
20
|
+
## Send Collector data to Logfire
|
|
21
|
+
|
|
22
|
+
Point the Collector's OTLP exporter at the exact Logfire origin selected during
|
|
23
|
+
authentication. The token authenticates the same way as any OTLP client:
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
exporters:
|
|
27
|
+
otlphttp/logfire:
|
|
28
|
+
endpoint: '<selected-logfire-origin>'
|
|
29
|
+
headers:
|
|
30
|
+
Authorization: '${env:LOGFIRE_TOKEN}'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Use the project-scoped write token created by the authentication flow's `projects use`
|
|
34
|
+
command. Follow its [credential handoff instructions](https://pydantic.dev/.well-known/agent-skills/logfire-instrumentation/references/auth.md#if-the-calling-skill-needs-a-write-token-not-just-a-cli-session) to place only the token value into a gitignored env file, Kubernetes Secret, or the deployment's existing secret manager without printing it. Set that credential as `LOGFIRE_TOKEN` wherever the Collector runs -- `${env:NAME}` is the Collector's own config-substitution syntax, resolved at startup, never hardcoded into the Collector config. Add the exporter to your metrics (and/or logs/traces) pipelines.
|
|
35
|
+
|
|
36
|
+
Full setup, topologies, and processors:
|
|
37
|
+
https://pydantic.dev/docs/logfire/guides/otel-collector/otel-collector-overview/
|
|
38
|
+
|
|
39
|
+
## Host metrics → Hosts page
|
|
40
|
+
|
|
41
|
+
Use the `hostmetrics` receiver. Each host that ships these metrics appears on the
|
|
42
|
+
**Hosts** page with CPU, memory, load, disk, and network charts.
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
receivers:
|
|
46
|
+
hostmetrics:
|
|
47
|
+
collection_interval: 60s
|
|
48
|
+
scrapers:
|
|
49
|
+
cpu:
|
|
50
|
+
metrics:
|
|
51
|
+
system.cpu.utilization:
|
|
52
|
+
enabled: true
|
|
53
|
+
memory:
|
|
54
|
+
metrics:
|
|
55
|
+
system.memory.utilization:
|
|
56
|
+
enabled: true
|
|
57
|
+
load:
|
|
58
|
+
disk:
|
|
59
|
+
filesystem:
|
|
60
|
+
include_virtual_filesystems: false
|
|
61
|
+
metrics:
|
|
62
|
+
system.filesystem.utilization:
|
|
63
|
+
enabled: true
|
|
64
|
+
network:
|
|
65
|
+
processes:
|
|
66
|
+
processors:
|
|
67
|
+
resourcedetection:
|
|
68
|
+
detectors: [env, system]
|
|
69
|
+
system:
|
|
70
|
+
hostname_sources: [os]
|
|
71
|
+
service:
|
|
72
|
+
pipelines:
|
|
73
|
+
metrics:
|
|
74
|
+
receivers: [hostmetrics]
|
|
75
|
+
processors: [resourcedetection]
|
|
76
|
+
exporters: [otlphttp/logfire]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Set `host.name` (and other host resource attributes) so hosts are identified
|
|
80
|
+
correctly. Guide:
|
|
81
|
+
https://pydantic.dev/docs/logfire/guides/otel-collector/host-monitoring/
|
|
82
|
+
|
|
83
|
+
**App-only alternative:** if you can't run a Collector but the app process should
|
|
84
|
+
report its host's metrics, call `logfire.instrument_system_metrics()` (Python,
|
|
85
|
+
needs the `system-metrics` extra). The Collector `hostmetrics` receiver is
|
|
86
|
+
preferred for true host coverage because it runs per host, independent of any app.
|
|
87
|
+
|
|
88
|
+
## Docker containers → Docker page
|
|
89
|
+
|
|
90
|
+
Use the `docker_stats` receiver — **Contrib-only, not in the core Collector image** (`otelcol-contrib`, not `otelcol`) — pointed at the Docker socket, and added to an active metrics pipeline (a receiver defined but never referenced under `service.pipelines` collects nothing):
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
receivers:
|
|
94
|
+
docker_stats:
|
|
95
|
+
endpoint: unix:///var/run/docker.sock
|
|
96
|
+
api_version: "1.44" # quoted string -- a bare float like 1.44 is rejected
|
|
97
|
+
|
|
98
|
+
service:
|
|
99
|
+
pipelines:
|
|
100
|
+
metrics:
|
|
101
|
+
receivers: [docker_stats]
|
|
102
|
+
exporters: [otlphttp/logfire]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Modern builds of the receiver auto-negotiate the API version; older builds
|
|
106
|
+
default to 1.25, too old for current Docker/OrbStack, so pin a recent version
|
|
107
|
+
to avoid API-version errors. The collector needs permission to read the socket:
|
|
108
|
+
mount `/var/run/docker.sock` into the container and run it as a user that can
|
|
109
|
+
read it (often `user: "0:0"` in Docker Compose) -- call out that Docker socket
|
|
110
|
+
access, especially as root, is effectively root-level control of the host
|
|
111
|
+
before doing this.
|
|
112
|
+
|
|
113
|
+
Group containers under the real host by passing the host name in from the
|
|
114
|
+
shell and adding a `resourcedetection` processor with the `env` detector to
|
|
115
|
+
the pipeline — setting `OTEL_RESOURCE_ATTRIBUTES` alone does nothing; nothing
|
|
116
|
+
reads that environment variable into the actual resource attributes without
|
|
117
|
+
it:
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
# docker-compose.yml
|
|
121
|
+
services:
|
|
122
|
+
otel-collector:
|
|
123
|
+
environment:
|
|
124
|
+
OTEL_RESOURCE_ATTRIBUTES: host.name=${HOST_NAME}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
```yaml
|
|
128
|
+
processors:
|
|
129
|
+
resourcedetection:
|
|
130
|
+
detectors: [env]
|
|
131
|
+
|
|
132
|
+
service:
|
|
133
|
+
pipelines:
|
|
134
|
+
metrics:
|
|
135
|
+
receivers: [docker_stats]
|
|
136
|
+
processors: [resourcedetection]
|
|
137
|
+
exporters: [otlphttp/logfire]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
HOST_NAME=$(hostname) docker compose up
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
A literal `$(hostname)` inside a Compose value does not expand -- it has to
|
|
145
|
+
come in from the shell.
|
|
146
|
+
|
|
147
|
+
If the collector runs in a container and the Logfire base URL is a
|
|
148
|
+
localhost/LAN address (self-hosted or local dev), reach the host via
|
|
149
|
+
`host.docker.internal` (add `extra_hosts: ["host.docker.internal:host-gateway"]`
|
|
150
|
+
in Compose), not `localhost` -- inside the container, `localhost` is the
|
|
151
|
+
collector itself. A public cloud Logfire URL needs no change.
|
|
152
|
+
|
|
153
|
+
Guide: https://pydantic.dev/docs/logfire/observe/docker/
|
|
154
|
+
|
|
155
|
+
## Kubernetes → Kubernetes page
|
|
156
|
+
|
|
157
|
+
Collect cluster state, per-node/per-pod metrics, and the `k8s.*` resource
|
|
158
|
+
attributes (`k8s.cluster.name`, `k8s.namespace.name`, `k8s.pod.name`,
|
|
159
|
+
`k8s.deployment.name`, ...) that drive the **Kubernetes** page. The recommended
|
|
160
|
+
pattern is two Collectors — a Deployment for cluster-level state
|
|
161
|
+
(`k8sclusterreceiver`) and a DaemonSet for per-node/pod metrics
|
|
162
|
+
(`kubeletstatsreceiver`) — plus the `k8sattributesprocessor` to stamp the same
|
|
163
|
+
`k8s.*` attributes onto traces from your applications.
|
|
164
|
+
|
|
165
|
+
Guide:
|
|
166
|
+
https://pydantic.dev/docs/logfire/guides/otel-collector/kubernetes-monitoring/
|
|
167
|
+
|
|
168
|
+
## Database / queue / cache servers → Metrics & Dashboards
|
|
169
|
+
|
|
170
|
+
The Collector ships receivers for common infrastructure services. Add the
|
|
171
|
+
relevant receiver and its metrics become queryable in the **Metrics** explorer
|
|
172
|
+
and available for **dashboard panels** and **alerts**:
|
|
173
|
+
|
|
174
|
+
| Service | Receiver | Example metric prefix |
|
|
175
|
+
|---------|----------|-----------------------|
|
|
176
|
+
| PostgreSQL | `postgresql` | `postgresql.*` |
|
|
177
|
+
| MySQL | `mysql` | `mysql.*` |
|
|
178
|
+
| Redis | `redis` | `redis.*` |
|
|
179
|
+
| MongoDB | `mongodb` | `mongodb.*` |
|
|
180
|
+
| Kafka | `kafkametrics` | `kafka.*` |
|
|
181
|
+
| RabbitMQ | `rabbitmq` | `rabbitmq.*` |
|
|
182
|
+
| Nginx | `nginx` | `nginx.*` |
|
|
183
|
+
| Apache HTTP | `apache` | `apache.*` |
|
|
184
|
+
| Elasticsearch | `elasticsearch` | `elasticsearch.*` |
|
|
185
|
+
| Memcached | `memcached` | `memcached.*` |
|
|
186
|
+
|
|
187
|
+
These receivers live in the OpenTelemetry Collector Contrib distribution. Match
|
|
188
|
+
the receiver to the services the project actually depends on (read
|
|
189
|
+
`pyproject.toml` / `package.json` / `docker-compose.yml` to detect them), and set
|
|
190
|
+
`service.instance.id` on each so per-instance metrics stay distinct.
|
|
191
|
+
|
|
192
|
+
## Cloud provider metrics → Metrics & Dashboards
|
|
193
|
+
|
|
194
|
+
- **GCP**: the `googlecloudmonitoring` receiver pulls Cloud Monitoring (formerly
|
|
195
|
+
Stackdriver) metrics — needs a service account with monitoring read
|
|
196
|
+
permissions and an explicit `metrics_list` of metric names to collect.
|
|
197
|
+
- **AWS**: the `awsecscontainermetrics` receiver reads ECS task-metadata-endpoint
|
|
198
|
+
metrics directly, no extra IAM beyond the task role. For broader CloudWatch
|
|
199
|
+
metrics (RDS, ALB, and other services not on the ECS metadata endpoint), use
|
|
200
|
+
the `awscloudwatch` receiver available in the stock Contrib distribution.
|
|
201
|
+
Configure `metrics.queries[].stats` or `metrics.discovery.stats` explicitly
|
|
202
|
+
(for example, `[Average]`) so the receiver emits Gauge points; omitted stats
|
|
203
|
+
produce Summary points. Logfire drops those points at ingest and emits a
|
|
204
|
+
`logfire ingest error`; payloads that mix supported and Summary points may be
|
|
205
|
+
partially ingested. It needs
|
|
206
|
+
`cloudwatch:GetMetricData` /
|
|
207
|
+
`GetMetricStatistics` / `ListMetrics` IAM permissions.
|
|
208
|
+
|
|
209
|
+
Full setup, IAM policies, and example ECS/Cloud Run deployments:
|
|
210
|
+
https://pydantic.dev/docs/logfire/guides/cloud-metrics/
|
|
211
|
+
|
|
212
|
+
## Service & resource metadata
|
|
213
|
+
|
|
214
|
+
Whatever the source, set resource attributes so data is grouped correctly across
|
|
215
|
+
the UI. From the Collector, use the `resource`/`resourcedetection` processors. The
|
|
216
|
+
`OTEL_RESOURCE_ATTRIBUTES` variable is consumed only when the `resourcedetection`
|
|
217
|
+
processor includes its `env` detector:
|
|
218
|
+
|
|
219
|
+
- `service.name`, `service.version`, `deployment.environment.name`
|
|
220
|
+
- `service.instance.id` — per-replica identity (standard dashboards filter on it)
|
|
221
|
+
- `host.name` — required for the Hosts page to identify a host
|
|
222
|
+
|
|
223
|
+
## Verify
|
|
224
|
+
|
|
225
|
+
After wiring a receiver + the Logfire exporter, restart the Collector and check
|
|
226
|
+
that the corresponding page (Hosts / Kubernetes) or the Metrics explorer shows
|
|
227
|
+
the new data within a minute or two. If nothing appears: confirm the exporter
|
|
228
|
+
endpoint/region and write token, that the receiver is in an active pipeline, and
|
|
229
|
+
that resource attributes (`host.name`, `service.name`) are set.
|