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

Sem Conv Laravel Package

open-telemetry/sem-conv

PHP constants for OpenTelemetry semantic conventions, generated from official releases. Provides stable attribute and metric names plus incubating/experimental ones, so instrumentation code can reference standard keys without hardcoding strings.

View on GitHub
Deep Wiki
Context7

Getting Started

open-telemetry/sem-conv contains no runtime code — it is a generated collection of PHP classes holding string constants for OpenTelemetry attribute names, metric names, and enum values. You "use" it by referencing those constants wherever you create spans, metrics, or resource attributes. If your instrumentation currently writes 'http.request.method' as a raw string, this package replaces that with HttpAttributes::HTTP_REQUEST_METHOD.

Minimal setup

composer require open-telemetry/sem-conv
composer show open-telemetry/sem-conv   # note the version — it mirrors the semconv schema release

You almost always need the SDK alongside it, otherwise the constants have nothing to feed:

composer require open-telemetry/sdk open-telemetry/exporter-otlp

Keep sem-conv, open-telemetry/sdk, and your exporter on compatible version ranges; the SDK's own composer.json constrains sem-conv, and a mismatched pair is the most common source of confusing attribute names.

Where to look first

  1. vendor/open-telemetry/sem-conv/ — browse the generated tree. The layout is:
    • OpenTelemetry\SemConv\Attributes\* — stable attribute keys (production-safe)
    • OpenTelemetry\SemConv\Metrics\* — stable metric names
    • OpenTelemetry\SemConv\Incubating\* — stable + experimental, use with caution
  2. Your IDE. Autocomplete on HttpAttributes::, DbAttributes::, ServiceAttributes::, MessagingAttributes:: is the fastest way to discover what exists. Class names are grouped by domain, constants carry the dotted key as their value.
  3. The upstream spec (https://opentelemetry.io/docs/concepts/semantic-conventions/) for the semantics — when to set an attribute, not just its name. The package gives you the spelling; the spec gives you the meaning.

First real use case: a root HTTP span

In a Laravel app the highest-value first step is a middleware that opens a server span for each request using stable conventions:

// app/Http/Middleware/TelemetryMiddleware.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use OpenTelemetry\API\Globals;
use OpenTelemetry\SemConv\Attributes\HttpAttributes;
use OpenTelemetry\SemConv\Attributes\ServerAttributes;
use OpenTelemetry\SemConv\Attributes\UrlAttributes;
use OpenTelemetry\SemConv\Attributes\ErrorAttributes;
use OpenTelemetry\SemConv\Attributes\ExceptionAttributes;

class TelemetryMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        $tracer = Globals::tracerProvider()->getTracer('laravel-app');
        $span = $tracer->spanBuilder($request->method() . ' ' . $request->route()?->uri() ?? '/')
            ->setSpanKind(\OpenTelemetry\API\Trace\SpanKind::KIND_SERVER)
            ->startSpan();

        $scope = $span->activate();

        try {
            $span->setAttributes([
                HttpAttributes::HTTP_REQUEST_METHOD => $request->method(),
                UrlAttributes::URL_PATH            => '/' . ltrim($request->path(), '/'),
                UrlAttributes::URL_SCHEME          => $request->getScheme(),
                ServerAttributes::SERVER_ADDRESS   => $request->getHost(),
                ServerAttributes::SERVER_PORT      => (int) $request->getPort(),
            ]);

            $response = $next($request);

            $span->setAttribute(HttpAttributes::HTTP_RESPONSE_STATUS_CODE, $response->getStatusCode());

            return $response;
        } catch (\Throwable $e) {
            $span->recordException($e, [
                ExceptionAttributes::EXCEPTION_TYPE => get_class($e),
            ]);
            $span->setAttribute(ErrorAttributes::ERROR_TYPE, get_class($e));
            throw $e;
        } finally {
            $scope->detach();
            $span->end();
        }
    }
}

Register it in bootstrap/app.php (Laravel 11+) or app/Http/Kernel.php. Verify with a local collector or dd($span->toSpanData()) in a scratch test before wiring dashboards.

Implementation Patterns

1. Never inline attribute strings — always go through constants

The whole point is a single source of truth. Establish a team rule: no string literals for OTel keys outside a small conventions wrapper. This pays off when a semconv upgrade renames keys: a grep for the constant finds every usage.

use OpenTelemetry\SemConv\Attributes\DbAttributes;

$span->setAttributes([
    DbAttributes::DB_SYSTEM_NAME   => 'mysql',
    DbAttributes::DB_OPERATION_NAME => 'SELECT',
    DbAttributes::DB_NAMESPACE     => $connection->getDatabaseName(),
]);

2. Domain-specific integration points in Laravel

The natural places to apply conventions map cleanly onto Laravel's event system:

  • Database — a DB::listen listener or a query-executed event listener wraps each query in a client span and sets db.system.name, db.operation.name, db.namespace, and db.query.text (newer conventions; older versions used db.system / db.statement — check your installed version).
  • Queue jobs — a job middleware or JobProcessing/JobProcessed listener creates producer/consumer spans with messaging.system, messaging.destination.name, messaging.operation.type (publish/process), and propagates context via the job payload so traces link across the worker boundary.
  • Cache — CacheHit/CacheMissed events map to a cache span with cache.hit / cache.key.
  • HTTP client — Guzzle middleware (Laravel's Http facade uses Guzzle) for outgoing spans: http.request.method, url.full, server.address, http.response.status_code.
  • Exceptions — recordException() plus the exception.type, exception.message, exception.stacktrace attributes; set error.type on the span so backends can aggregate error rates.

3. Resource attributes are set once, at provider bootstrap

Semantic conventions apply to the Resource, not just spans. In a service provider:

use OpenTelemetry\SDK\Common\Attribute\Attributes;
use OpenTelemetry\SDK\Resource\ResourceInfo;
use OpenTelemetry\SemConv\Attributes\ServiceAttributes;
use OpenTelemetry\SemConv\Attributes\DeploymentAttributes;

$resource = ResourceInfo::create(Attributes::create([
    ServiceAttributes::SERVICE_NAME    => config('app.name'),
    ServiceAttributes::SERVICE_VERSION => config('app.version', 'dev'),
    DeploymentAttributes::DEPLOYMENT_ENVIRONMENT_NAME => app()->environment(),
]));

Be aware deployment.environment was renamed to deployment.environment.name in recent schemas — a classic silent dashboard break.

4. Pick metrics constants for instruments, attributes for dimensions

When you create a counter or histogram, name it from OpenTelemetry\SemConv\Metrics\* and use attribute constants for its label set, so Prometheus/Datadog series line up with other services:

use OpenTelemetry\SemConv\Metrics\HttpMetrics;
use OpenTelemetry\SemConv\Attributes\HttpAttributes;

$histogram = $meter->createHistogram(HttpMetrics::HTTP_SERVER_REQUEST_DURATION, 's');
$histogram->record($durationSeconds, [
    HttpAttributes::HTTP_REQUEST_METHOD      => $request->method(),
    HttpAttributes::HTTP_ROUTE               => $route,
    HttpAttributes::HTTP_RESPONSE_STATUS_CODE => $status,
]);

5. Stable vs incubating discipline

Import stable classes (OpenTelemetry\SemConv\Attributes\*) in production code by default. Reach into OpenTelemetry\SemConv\Incubating\* only when the attribute you need hasn't stabilized yet — and treat those imports as upgrade-sensitive. A pragmatic convention: keep all incubating imports in one file (your telemetry bootstrap or a Conventions wrapper) so they're easy to audit on upgrade.

6. Thin wrapper for ergonomics and testability

A tiny class in app/Telemetry/Conventions.php that re-exports only the constants you actually use has two benefits: it documents your telemetry surface, and it gives you one place to adapt when a rename lands.

final class Conventions
{
    // Re-export what the app uses; grep this file on upgrade.
}

7. Test your emitted telemetry, not just the constants

Use an in-memory span exporter in a feature test and assert on raw string keys ($attributes['http.request.method']), not on the constant. Asserting on the constant makes the test pass even after a rename — exactly the failure you want to catch.

Gotchas and Tips

Deprecations are removed immediately. The README is explicit: deprecated conventions are dropped in the next release with no backwards-compatibility guarantee. Upgrading sem-conv is a code-change task, not a lockfile bump. Run composer update open-telemetry/sem-conv --dry-run, read the diff, then grep -rn "SemConv" app/ and fix every constant.

Version the package against your pipeline, not against "latest." Semconv version is only meaningful relative to what your collector, backend, and dashboards understand. Pin the package ("open-telemetry/sem-conv": "1.38.*") if your collector is pinned. The 1.44.0 release rolls up schema versions 1.39–1.44 in one step — treating that as a coordinated change (package + instrumentation + dashboards + saved queries + alerts) is far safer than six unsynchronized bumps.

Common renames to search for after upgrading:

  • http.method → http.request.method
  • http.status_code → http.response.status_code
  • http.url / http.target → url.full / url.path
  • db.system → db.system.name, db.statement → db.query.text
  • deployment.environment → deployment.environment.name
  • net.peer.* → server.* / client.*
  • exception.* semantics shifted to error.* for error classification.

Namespace structure changed in 1.36.0, and the incubating namespace was fixed in 1.38.0. Code written against pre-1.36 docs (OpenTelemetry\SemConv\TraceAttributes::HTTP_METHOD) will not compile. On 1.38.0+ the incubating namespace is corrected — if you're on anything older and using incubating constants, upgrade. Verify actual constant names against vendor/ rather than blog posts; the generated surface varies by release.

These are plain strings — nothing validates them. A typo compiles, runs, and silently produces an attribute your dashboard ignores. IDE autocomplete is your main defense; consider a lint/CI check that forbids string literals matching known attribute patterns in instrumentation files.

The package alone does nothing. No tracer, no exporter, no configuration. If you composer require this and see no spans, that's expected — you still need open-telemetry/sdk, an exporter, and OTEL_* env vars (or a declarative config provider). It's also common for open-telemetry/sdk to pull sem-conv transitively; require it explicitly only when your code references the constants directly (which it should).

Attribute values are also part of the contract. Enum-ish values (e.g. messaging.operation.type → publish/process/create, db.operation.name → uppercase SELECT) are specified. Where the package exposes value enums/constants, use them; where it doesn't, cross-check the spec. Backend cardinality and aggregation break as fast from wrong values as from wrong keys.

Don't use conventions for custom dimensions. If an attribute genuinely isn't in the spec, define your own constant with a vendor/domain prefix and keep it clearly separate from SemConv\* usages. Mixing custom keys into the standard namespace makes future upgrades ambiguous.

Schema URL drift. The package is generated per semconv release; if you emit data tagged with one schema version into a pipeline assuming another, collectors may drop or mis-map attributes. Check whether your SDK exposes a schema-URL/semconv version setting (an enum for semconv versions has existed since 1.27) and keep it aligned with the package version.

PHP baseline. The monorepo targets PHP 8.2 minimum and uses polyfills for newer versions. If your Laravel app runs an older PHP, stay on an older sem-conv release — a composer update that pulls a newer sem-conv may raise the floor unexpectedly.

Static analysis noise. Thousands of constant-holding classes can bloat classmaps and slow some tooling marginally; that's the cost of generated code. Exclude vendor/open-telemetry/sem-conv from Rector/PHPStan where it's irrelevant — you're never editing it.

Extension point: your own telemetry contract layer. The only sane extension point is around this package, not inside it (it's a read-only subtree split — PRs go to the main monorepo). Wrap it in your app: one conventions file, one tracer/meter factory, one middleware stack. That layer is what you change when semconv renames things, keeping the blast radius small.

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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo