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

Sdk Configuration Laravel Package

open-telemetry/sdk-configuration

Configuration layer for the OpenTelemetry PHP SDK, resolving settings from environment variables, php.ini, and declarative config files so instrumentation and exporters can be configured consistently without code changes.

View on GitHub
Deep Wiki
Context7

Getting Started

open-telemetry/sdk-configuration is the configuration layer of the OpenTelemetry PHP SDK: an immutable SdkConfiguration value object plus the env-var / php.ini resolution that fills it, following the OpenTelemetry SDK configuration spec. It contains no exporters, no HTTP client, no auto-instrumentation. Its entire job is to answer "what did the operator ask for?" and hand back constructed (lazily) providers.

Two things to internalise before touching it:

  1. It is a READONLY subtree split of open-telemetry/opentelemetry-php. That's why it has ~0 stars. Never file issues or PRs here — they go to the monorepo. Don't composer require it directly either; it arrives transitively via open-telemetry/sdk (or any exporter/instrumentation package).
  2. It's infrastructure, not a product. It ships in lockstep with the monorepo, is spec-driven, and changes rarely. Treat it as a stable ABI you configure, not a library you extend.

Where to look first, in order:

  • SdkConfiguration — its property list is the supported env-var matrix. Skim it once and you know every knob (OTEL_SERVICE_NAME, OTEL_TRACES_SAMPLER, OTEL_TRACES_EXPORTER, OTEL_EXPORTER_OTLP_*, OTEL_PROPAGATORS, OTEL_SDK_DISABLED, ...).
  • SdkConfigurationFactory::create() — the normal entry point.
  • Environment/EnvReader and Environment/Resolver — precedence and parsing rules (this is where most surprise lives).
  • The upstream spec's "Environment Variable" table — the package is a literal transcription of it.

Minimal first use case in a Laravel app: you're adding open-telemetry/sdk + open-telemetry/exporter-otlp and want .env-driven tracing.

composer require open-telemetry/sdk open-telemetry/exporter-otlp
use OpenTelemetry\SDK\Configuration\SdkConfigurationFactory;

$config = SdkConfigurationFactory::create();  // reads OTEL_* from the environment
$tracer = $config->getTracerProvider()->getTracer('laravel');

$span = $tracer->spanBuilder('handle-request')->startSpan();
// ... work ...
$span->end();

If that produces a working span, the package is doing its job and you can stop reading. Everything below is about the 20% of cases where it isn't.

Implementation Patterns

1. Env-var-first (let ops own it). The zero-code path: put OTEL_* variables in .env, docker-compose.yml, or your k8s deployment and never write PHP. This is the intended usage and the cheapest to maintain.

OTEL_SERVICE_NAME=checkout-api
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=0.05
OTEL_PROPAGATORS=tracecontext,baggage

2. Laravel config/ as source of truth, translated into SdkConfiguration. Use this when you need config:cache, per-environment files, package config merging, or secret indirection. Resolve once in a service provider, build the object, and register it so every downstream SDK call (instrumentations, exporters, middleware) sees your values instead of raw env.

// config/opentelemetry.php
return [
    'service_name'  => env('OTEL_SERVICE_NAME', env('APP_NAME', 'laravel')),
    'endpoint'      => env('OTEL_EXPORTER_OTLP_ENDPOINT'),
    'protocol'      => env('OTEL_EXPORTER_OTLP_PROTOCOL', 'http/protobuf'),
    'headers'       => env('OTEL_EXPORTER_OTLP_HEADERS', ''),
    'sampler'       => env('OTEL_TRACES_SAMPLER', 'parentbased_always_on'),
    'disabled'      => (bool) env('OTEL_SDK_DISABLED', false),
];
// AppServiceProvider::register()
public function register(): void
{
    $c = config('opentelemetry');

    $config = new \OpenTelemetry\SDK\Configuration\SdkConfiguration(
        serviceName: $c['service_name'],
        // ... rest of the named args, derived from $c
    );

    \OpenTelemetry\SDK\Configuration\ConfigurationRegistry::set($config);
}

The payoff: one place (config/opentelemetry.php) that is cacheable, greppable, and testable, instead of env vars leaking in from a dozen deployment layers.

3. Explicit construction in tests. Build a SdkConfiguration with named arguments (or a small helper/factory in tests/Support) rather than mutating $_ENV. It's a plain value object — that's the most underrated feature of the package. Pair it with ConfigurationRegistry::reset() in tearDown.

4. Resource attributes as the first-class citizen. service.name defaults to unknown_service:php, which makes traces unfindable. Always set OTEL_SERVICE_NAME / OTEL_RESOURCE_ATTRIBUTES (deployment.environment, service.version, team) — or pass a ResourceInfo and let it merge. Do this at boot, not per request.

5. Octane / queue workers. Resolve config once per worker at boot; the provider is process-scoped and safe to share. Your per-request responsibility is only span->end() and context propagation across jobs via OTEL_PROPAGATORS.

6. You're already using it. If you run keepsuit/laravel-opentelemetry, spatie/laravel-open-telemetry, or the OTel PHP extension, this package is under them. Reading its property list is the fastest way to understand their config files, and gives you the vocabulary to debug collector connection failures.

Gotchas and Tips

  • Version lockstep. sdk-configuration and open-telemetry/sdk share the Context/ConfigProperties interfaces. Mismatched majors produce confusing interface errors. Let Composer resolve; never pin this one manually.
  • config:cache and env() — the trap that doesn't apply. env() returns null outside config files once cached, but this package does not use env(); it reads $_SERVER / $_ENV (with a getenv() fallback). So OTEL_* in .env keeps working even with cached config — which contradicts every Laravel reflex and confuses people both ways. Verify with:
    php -r 'var_dump($_ENV["OTEL_SERVICE_NAME"] ?? $_SERVER["OTEL_SERVICE_NAME"] ?? null);'
    
  • Fail-fast, and it fails at boot. Invalid enum values (OTEL_TRACES_EXPORTER=garbage, malformed header lists) throw InvalidArgumentException when SdkConfiguration is constructed — i.e. inside a service provider's register(), producing a stack trace that points at framework bootstrap rather than your typo. Validate in config/opentelemetry.php or wrap the bootstrap in try/catch + log.
  • Silent degradation is the norm. Missing auth, unknown protocols, and dropped attributes are logged through the SDK's internal Logging API, not thrown. Set OTEL_LOG_LEVEL=debug and wire a PSR-3 logger, or you'll chase 401s from the collector with zero local evidence.
  • OTEL_EXPORTER_OTLP_HEADERS parsing. Comma-separated key=value, values are URL-decoded, and a comma inside a value must be percent-encoded. Same shape for OTEL_RESOURCE_ATTRIBUTES. Getting this subtly wrong drops the header and looks like a collector outage.
  • Generic vs per-signal endpoints. OTEL_EXPORTER_OTLP_TRACES_ENDPOINT overrides OTEL_EXPORTER_OTLP_ENDPOINT. Setting the wrong one is a classic "why is nothing exported" bug. Likewise 4317 (gRPC) vs 4318 (HTTP) — default ports differ by protocol, and http/json is not fully supported.
  • Sampler is decided at provider construction. Changing OTEL_TRACES_SAMPLER requires a worker restart; it is not re-read per request. Default is parentbased_always_on — fine for staging, expensive in production.
  • OTEL_PHP_* is not yours. OTEL_PHP_AUTOLOAD_ENABLED, OTEL_PHP_EXCLUDED_URLS belong to the native extension / auto-instrumentation. SdkConfiguration ignores them — don't expect this package to honour them, and don't assume their presence means tracing is on.
  • Constructor churn. SdkConfiguration::__construct has ~40 named parameters and gains/renames them across minors. Prefer SdkConfigurationFactory or the registry, and add one test asserting your hand-built config still round-trips after upgrades.
  • The registry is a global static. ConfigurationRegistry::set() / get() / reset() is convenient but dangerous: mutating it per-request under Octane leaks config between requests, and forgetting reset() leaks between tests. Treat it as write-once-at-boot.
  • Resource merging is silent. If you pass a ResourceInfo and set OTEL_RESOURCE_ATTRIBUTES, they merge and later values win with no warning. Decide on one source of truth per attribute.
  • Debugging ladder: OTEL_LOG_LEVEL=debug → dump the resolved SdkConfiguration → confirm getTracerProvider() is not a no-op (OTEL_SDK_DISABLED=true silently gives you one — useful as an emergency kill switch, terrible when set by accident) → confirm sampler → only then suspect the network.
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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource