{"id":49376139,"url":"https://github.com/microscaler/microscaler-observability","last_synced_at":"2026-04-28T02:30:37.241Z","repository":{"id":352611842,"uuid":"1214478795","full_name":"microscaler/microscaler-observability","owner":"microscaler","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-20T10:37:37.000Z","size":151,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-20T12:36:38.287Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/microscaler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-18T16:25:02.000Z","updated_at":"2026-04-20T10:37:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/microscaler/microscaler-observability","commit_stats":null,"previous_names":["microscaler/microscaler-observability"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/microscaler/microscaler-observability","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microscaler%2Fmicroscaler-observability","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microscaler%2Fmicroscaler-observability/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microscaler%2Fmicroscaler-observability/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microscaler%2Fmicroscaler-observability/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/microscaler","download_url":"https://codeload.github.com/microscaler/microscaler-observability/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microscaler%2Fmicroscaler-observability/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32363540,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-27T20:07:02.737Z","status":"online","status_checked_at":"2026-04-28T02:00:07.250Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-28T02:30:34.574Z","updated_at":"2026-04-28T02:30:37.230Z","avatar_url":"https://github.com/microscaler.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# microscaler-observability\n\n**Hexagonal observability adapter for the microscaler platform.**\n\nCluster OTLP endpoints and env vars: see [`docs/CLUSTER_OBSERVABILITY.md`](docs/CLUSTER_OBSERVABILITY.md).\n\nThis crate is the single place in the workspace that owns OpenTelemetry\nglobal state — `TracerProvider`, `LoggerProvider`, `MeterProvider`, and\nthe W3C propagator. It sits alongside [BRRTRouter](../BRRTRouter/)\n(HTTP adapter) and [Lifeguard](../lifeguard/) (Postgres adapter) as a\n**peer** in the ports-and-adapters architecture, not as a child of either.\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                     Host app (main.rs)                   │\n│  ┌────────────────────────────────────────────────────┐  │\n│  │                  DOMAIN (core)                     │  │\n│  │    handler impls, business logic, domain types     │  │\n│  │         emits: tracing::info!, tracing::span!      │  │\n│  └────────────────────────────────────────────────────┘  │\n│        ▲                    │                   │        │\n│        │                    │                   │        │\n│     input              output (DB)         output (OTEL) │\n│        │                    │                   │        │\n│  ┌─────┴──────┐    ┌────────┴──────┐    ┌───────┴──────┐ │\n│  │ BRRTRouter │    │   Lifeguard   │    │  THIS CRATE  │ │\n│  │ (HTTP in)  │    │ (Postgres out)│    │  (OTEL out)  │ │\n│  │  also out: │    │   emits:      │    │              │ │\n│  │  HTTP resp │    │ tracing::*    │    │ owns:        │ │\n│  │  emits:    │    │               │    │ TracerProvid.│ │\n│  │ tracing::* │    │               │    │ LoggerProvid.│ │\n│  │            │    │               │    │ MeterProvid. │ │\n│  │            │    │               │    │ Propagator   │ │\n│  └────────────┘    └───────────────┘    └──────────────┘ │\n└──────────────────────────────────────────────────────────┘\n```\n\n## Why it exists\n\nOriginally (pre-v0.4 of the cross-repo PRD), BRRTRouter's\n`init_logging_with_config` did double duty as the observability adapter.\nLifeguard separately installed its own `MeterProvider` via an `OnceCell`.\nWhen [Hauliage](../hauliage/) grew up into a real domain app composing both,\ntwo smells emerged:\n\n1. **Wrong coupling.** Services that use only BRRTRouter (without a DB) still\n   carried Lifeguard's meter-provider installer in the dep graph. Services\n   that use only Lifeguard (CLI tools, migrations) had nowhere clean to init\n   OTEL without pulling in the whole HTTP framework.\n2. **Global-state race.** Lifeguard's `set_meter_provider` call fired\n   whenever `LifeguardMetrics::init()` ran; if BRRTRouter ever also tried to\n   set it, whoever ran first won — silently.\n\nPulling all OTEL init into a dedicated, neutral crate fixes both. BRRTRouter\nand Lifeguard become pure emitters (`tracing::span!` / `tracing::info!`) that\nnever touch `opentelemetry::global::*`. This crate owns init; `main()` owns\nlifecycle.\n\nSee `docs/PRD.md` for the complete architectural rationale and the cross-repo\nmigration plan.\n\n## Who uses it\n\nAs of v0.0.1, **nothing yet** — the crate is a scaffold. `init()` deliberately\npanics with an instruction pointing at the PRD, so integration shape can be\nvalidated without accidental success against a stub.\n\nOnce Phase O.1 of `docs/PRD.md` ships, consumers look like:\n\n- **Hauliage** (the primary driver — real domain, real DB, real dashboards):\n  Each of the ~17 microservices' `main.rs` calls `init()` first, holds the\n  `ShutdownGuard` for process lifetime, then wires its BRRTRouter server +\n  Lifeguard pool + domain handlers.\n- **BRRTRouter examples** (pet_store, etc.): Same pattern.\n- **Lifeguard CLI tools** (migrations, reflector, health-checks): Same\n  pattern, just without the HTTP layer.\n\n## Version coupling\n\n**`opentelemetry = \"0.29\"`** is pinned to match Lifeguard's\n[`Cargo.toml`](../lifeguard/Cargo.toml) (currently `opentelemetry = \"0.29.1\"`,\n`opentelemetry_sdk = \"0.29.0\"`, `opentelemetry-prometheus = \"0.29.1\"`).\n\nIf both crates ever see different `opentelemetry` majors, their global-state\nslots are *different slots at the same name* — traces emit fine from one side\nbut are invisible from the other. Any bump is a coordinated cross-repo change,\nnot a unilateral one. See `docs/PRD.md` §Phase O.0 for the pinning contract.\n\n## Feature flags\n\n| Feature                   | Default | Purpose |\n|---------------------------|:-------:|---------|\n| `dev-stdout-fallback`     | ✅      | When `OTEL_EXPORTER_OTLP_ENDPOINT` is unset, install a plain `tracing_subscriber::fmt` layer to stdout so `cargo test` / `cargo run` still show logs locally. Disable in release builds that want the \"stdout is startup-only\" invariant enforced at compile time. |\n| `profiling`               | ❌      | Bring in `pyroscope-rs` for push-mode continuous profiling (flamegraphs). Activated by setting `PYROSCOPE_SERVER_ADDRESS` at runtime. |\n| `http-proto` / `http-json`| ❌      | Alternate OTLP transports. Default is `grpc-tonic`. |\n\n## Env var contract\n\nAll OTEL-standard variables per the [OpenTelemetry specification][otel-spec]\nare honoured. A subset that matters most:\n\n| Env var                           | Default             | Effect |\n|-----------------------------------|---------------------|--------|\n| `OTEL_EXPORTER_OTLP_ENDPOINT`     | unset               | When unset, OTLP is disabled and stdout-fallback is used (if the feature is on). When set (e.g. `http://otel-collector:4317`), all three pipelines route through OTLP. |\n| `OTEL_EXPORTER_OTLP_PROTOCOL`     | `grpc`              | `grpc` / `http/protobuf` / `http/json` |\n| `OTEL_SERVICE_NAME`               | *(required)*        | Appears as the service name in Jaeger / Loki. |\n| `OTEL_SERVICE_VERSION`            | `CARGO_PKG_VERSION` | Resource attr; set by caller via `.with_service_version()`. |\n| `OTEL_RESOURCE_ATTRIBUTES`        | empty               | Extra `k=v,k=v` resource attrs (e.g. `deployment.environment=dev`). |\n| `OTEL_TRACES_SAMPLER`             | `parentbased_always_on` | Standard OTEL sampler name. |\n| `OTEL_TRACES_SAMPLER_ARG`         | `1.0`               | Ratio for ratio-based samplers. |\n| `RUST_LOG`                        | `info`              | `tracing` filter. Merged into the subscriber's `EnvFilter`. |\n| `BRRTR_DEV_LOGS_TO_STDOUT`        | `0`                 | Break-glass override: even if OTLP is configured, also install the stdout fallback layer so operators can see logs in `kubectl logs` during a debugging session. Set to `1` to enable. |\n\nOne crate-specific knob with a `MICROSCALER_` prefix exists only where no\nOTEL-standard variable covers the concern.\n\n## Non-goals (for now)\n\n- **Installing a `MeterProvider`.** v0.0.1 and Phase O.1 deliberately leave\n  metrics in BRRTRouter's existing Prometheus-text `/metrics` endpoint,\n  concatenated with Lifeguard's `prometheus_scrape_text()`. If downstream OTLP\n  metrics ever become necessary, the OTEL Collector's Prometheus receiver\n  re-exports them via OTLP without any application change. See `docs/PRD.md`\n  Phase O.6.\n- **Vendor-specific APM integrations** (Datadog, Honeycomb, New Relic). OTLP\n  is the contract; vendor translation is the Collector's job.\n- **Custom sampling policies beyond the standard OTEL-SDK samplers.** Tail\n  sampling is a Collector concern.\n\n## Related docs\n\n- [`docs/PRD.md`](docs/PRD.md) — **Cross-repo master PRD.** Authoritative source\n  for the migration plan, phase sequencing, and ownership contract between\n  this crate, BRRTRouter, Lifeguard, and Hauliage.\n- [`../BRRTRouter/docs/PRD_OBSERVABILITY_AND_TRACING.md`](../BRRTRouter/docs/PRD_OBSERVABILITY_AND_TRACING.md)\n  — Historical draft (v0.1–v0.3) that predates this crate's creation. Retained\n  for context; the master plan lives here.\n- [`../lifeguard/docs/OBSERVABILITY_APP_INTEGRATION.md`](../lifeguard/docs/OBSERVABILITY_APP_INTEGRATION.md)\n  — Lifeguard's pre-existing integration contract. This crate honours its four\n  rules (one TracerProvider, one subscriber, Lifeguard declines OTel globals,\n  `channel_layer()` is optional).\n- [`../hauliage/k8s/observability/README.md`](../hauliage/k8s/observability/README.md)\n  — The five existing Grafana dashboards Hauliage already ships. This crate's\n  output must satisfy and extend them without breakage.\n\n[otel-spec]: https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/\n\n## License\n\nApache-2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicroscaler%2Fmicroscaler-observability","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicroscaler%2Fmicroscaler-observability","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicroscaler%2Fmicroscaler-observability/lists"}