Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Observability Bundle Laravel Package

micro-module/observability-bundle

Observability bundle for Laravel/PHP applications that centralizes logging, metrics, and tracing configuration. Provides opinionated defaults and simple setup so teams can monitor requests, errors, and performance without wiring multiple packages.

View on GitHub
Deep Wiki
Context7

Getting Started

First, confirm the fit. This is a Symfony bundle — it ships a Bundle class, a DependencyInjection\Extension with a Configuration tree, and compiler passes. Laravel will not auto-discover it, will not read its config tree, and will not dispatch its Symfony event subscribers. You are not consuming this package so much as reading it and porting its loading model. Budget for that before installing anything.

Minimal evaluation path:

  1. composer require micro-module/observability-bundle in a scratch Symfony skeleton (not your Laravel app) just to see the config surface. Read, in this order: the bundle class, DependencyInjection/*Extension.php, DependencyInjection/Configuration.php, then the compiler passes — that is where the "conditional subsystem loading" actually lives.
  2. Note the subsystem flags (tracing / metrics / logging), the exporter settings (OTLP endpoint, protocol), sampler config, and resource attributes. These are your requirements doc.
  3. In your Laravel app, install open-telemetry/opentelemetry-php plus open-telemetry/exporter-otlp and run a local collector (OTel Collector → Jaeger/Tempo). Do not point at a hosted backend until you see spans locally.
  4. First real use case: tracing only, HTTP server spans via middleware, service.name and deployment.environment as resource attributes. Leave metrics and logs disabled until traces are clean — that is the same discipline the bundle's conditional loading is trying to enforce.

If the port looks like more than a day of work, fall back to open-telemetry/opentelemetry-php directly and treat this repo as a reference architecture, not a dependency. With zero stars and zero dependents you have no upstream safety net either way.

Implementation Patterns

Mirror the conditional-loading idea with a Laravel config file. The bundle's core value is that a disabled subsystem costs nothing at container build time. Reproduce that with config/observability.php (tracing.enabled, metrics.enabled, logs.enabled) and a service provider that only binds the tracer/exporter/middleware when the flag is true. Resolve everything as singletons so one TracerProvider and one MeterProvider exist per process.

HTTP server spans — middleware wrapped around the request, span started on handle(), ended and status set in a finally, attributes for route, method, status code after the response is built. Use the route pattern (users/{id}), not the resolved URL, or you get unbounded cardinality.

Queue jobs — this is the Symfony Messenger-to-Laravel-Queue translation. Hook JobProcessing / JobProcessed / JobFailed and create a consumer span per job, with the trace context serialized onto the payload when dispatching so the producer and consumer spans link. Without the propagation step you get two disconnected traces and the feature looks broken.

Database and outbound HTTP — DB::listen for query spans (statement template only, never bound values), and Http::globalRequestMiddleware / a Guzzle middleware for client spans with W3C traceparent injected. Keep both behind their own config flags; on a write-heavy app these are the two hooks that will actually cost you throughput.

Console — wrap Artisan via Artisan::starting so scheduled commands produce spans; otherwise your cron noise is invisible and you'll misattribute latency.

Export pipeline — BatchSpanProcessor, OTLP over HTTP/protobuf unless you already run gRPC infra. Register a flush on app()->terminating() so short-lived requests and queue workers don't drop the final batch.

Propagation — extract inbound traceparent in the HTTP middleware, inject outbound on HTTP clients and queue dispatches. Set W3C TraceContext + Baggage as the propagator explicitly; the defaults across SDK versions have moved around.

Gotchas and Tips

  • This is not a Laravel package. No extra.laravel.providers, no php artisan vendor:publish, no Laravel-shaped config. Any blog post or README example for this bundle will be Symfony YAML that does not translate. Expect to rewrite the wiring, not configure it.
  • Silent no-ops from conditional loading. The whole point of the feature is that disabled subsystems vanish. The failure mode is "why are there no spans" with no error. Check the flags, then dump the resolved container (php artisan about won't help — add a temporary app()->bound(...) assertion).
  • Octane / long-running workers. Providers are resolved once; a span started in request A and not closed will leak into request B, and batch processors accumulate. Reset or scope the tracer per request, and confirm the SDK version you pin handles worker restarts. This is the single most common way an OTel integration corrupts an app in production.
  • Termination and flush. If you don't flush on terminate, your shortest, fastest, most interesting requests are the ones that lose their spans. Test by killing a request early.
  • Zero stars, zero dependents means no BC promise, no security advisory feed, no upgrade guides. Pin an exact version or a commit hash, and if you adopt the code, vendor it or fork it — you are the maintainer now.
  • Semantic conventions drift. Use the current stable semconv constants rather than string keys like http.status_code; the HTTP attribute names were reorganized in recent SDK releases and string literals will silently land in the wrong place.
  • Cardinality is the real cost. Resource attributes and span names are cheap; per-request attributes like user IDs, raw URLs, or query strings will blow up your backend bill before they blow up your latency.
  • Debug with a local collector and the console exporter first. If spans appear in stderr but not in your backend, it's an exporter/auth/endpoint problem, not an instrumentation problem — that distinction saves the most time.
  • Extension points worth knowing: custom SpanProcessor for redaction or enrichment, ResourceDetector for host/container attributes, and a custom sampler if tail-based sampling isn't available. All three exist in the SDK and are where the bundle's opinionated bits are least likely to be worth porting.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core