NAME
Punk::OpenTelemetry::Schema - schema URLs and the version converter
SYNOPSIS
my $schema = Punk::OpenTelemetry::Schema->load(path => $file);
$schema->convert($payload,
from => '1.29.0', to => '1.30.0', signal => 'spans');
DESCRIPTION
Two halves: emitting the schema URL, and converting telemetry between the convention versions two schema URLs name.
EMITTING
Resource and each scope carry a schema_url, which travels as ResourceSpans.schema_url and ScopeSpans.schema_url - and the metrics and logs equivalents. The URL names the semantic convention version the telemetry was produced against.
The version this distribution emits is pinned in one header (OTEL_SCHEMA_URL in otel_semconv.h) and reachable as Punk::OpenTelemetry::Instrument::schema_url, so "which conventions does this speak" has an answer that cannot drift from the code.
A resource and a scope may legitimately carry different schema URLs, and telemetry with different URLs must not be merged into one ResourceSpans - the grouping key is the resource plus the schema URL. That is what makes this more than a string field.
CONVERTING
Order matters, and so does direction
Versions are applied one at a time, in order. A single merged rename map computed in one pass gives the wrong answer whenever an attribute was renamed twice: a becomes b in one version and b becomes c in the next, so the right answer for a is c - but a flattened map holds a => b and b => c as independent entries and stops at b.
Applying versions forward is the reverse of applying them backward. A schema file records the changes made going up to each version, so forward renames old to new and backward renames new to old.
all applies to every signal and is merged before the signal's own section.
Where the files come from
Schema files live at their schema URL. Nothing here fetches over the network, under any configuration. A runtime dependency on a third party, in the request path, is not something a telemetry layer gets to introduce quietly.
So the file for the version this dist emits ships with it, at Punk/OpenTelemetry/Schema/1.30.0.yaml - unmodified, as published. That is the version this SDK's own telemetry is produced against, which makes it the one a caller almost always wants, and load() with no arguments finds it with no configuration.
Anything else is looked for on a search path, in this order:
The path exists for the operator who needs a version this release predates: drop the file in a directory, point OTEL_SCHEMA_DIR at it, and no code changes. Files are named version.yaml, and a version that is not a version (anything outside digits and dots) is refused rather than concatenated into a path.
An unknown schema URL is not an error. for_url returns undef, and the telemetry passes through unchanged - which is the correct outcome and the only one that does not involve reaching out to a third party mid-request.
Why bother
Honestly: most operators will never use the converter. It matters for one situation, which is common enough to be worth it - a fleet mid-upgrade, where half the services emit http.method and half emit http.request.method, and the dashboards break in a way that looks like an outage. Normalising at the edge makes that a config change rather than a coordinated redeploy.
METHODS
load(path => $file) / load(text => $yaml)
A schema file read from disk, or parsed from a string already in hand. The string form is what a test uses; the path form is for a schema this distribution does not ship.
load() / load(version => $v, dir => $d)
With no source, the shipped file for the version this dist emits. With a version, that version off the search path above. Dies when there is no such file, because a caller who named a version meant it.
for_url($schema_url)
The schema for a URL, or undef when nothing local describes it. This is the form to use when converting telemetry that arrived carrying its own schema URL: undef means leave it alone.
file_for($version)
The path the search would use, or undef.
shipped_version
The semantic convention version this distribution emits, derived from the C pin (OTEL_SCHEMA_URL in otel_semconv.h) so the two cannot drift.
convert($payload, from => $v, to => $v, signal => $s)
$signal is spans, metrics or logs. The payload is modified in place and returned.
schema_url / versions / knows($version)
schema_url is the URL this loaded schema describes. versions is the version list in file order, and in scalar context their count rather than the last of them. knows is whether a given version appears in it, which is what to ask before handing convert below a version a caller supplied.
SEE ALSO
Punk::OpenTelemetry::Instrument - where the emitted schema URL is pinned.
Punk::OpenTelemetry::Encode - the six schema_url fields on the wire.
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION <email@lnation.org>.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)