Qyl.Telemetry.SemanticConventions
9.1.0
See the version list below for details.
dotnet add package Qyl.Telemetry.SemanticConventions --version 9.1.0
NuGet\Install-Package Qyl.Telemetry.SemanticConventions -Version 9.1.0
<PackageReference Include="Qyl.Telemetry.SemanticConventions" Version="9.1.0" />
<PackageVersion Include="Qyl.Telemetry.SemanticConventions" Version="9.1.0" />
<PackageReference Include="Qyl.Telemetry.SemanticConventions" />
paket add Qyl.Telemetry.SemanticConventions --version 9.1.0
#r "nuget: Qyl.Telemetry.SemanticConventions, 9.1.0"
#:package Qyl.Telemetry.SemanticConventions@9.1.0
#addin nuget:?package=Qyl.Telemetry.SemanticConventions&version=9.1.0
#tool nuget:?package=Qyl.Telemetry.SemanticConventions&version=9.1.0
Qyl.Telemetry.SemanticConventions
.NET packages generated by Weaver from one
semantic-convention registry. registry/manifest.yaml is the single
source of truth for the upstream pins: it names the pinned core registry and the separately
pinned development GenAI registry as dependencies, and qyl's own YAML sits next to them under
registry/.
This is the one artifact both halves of qyl share: what an application emits and what the collector recognizes are generated from the same registry, so qyl cannot emit an attribute name its own collector does not know.
Packages
| Package | Contents |
|---|---|
Qyl.Telemetry.SemanticConventions |
The stable tier, pre-generated: attribute-key constants (every enum-value class carries AllValues and Contains), SchemaUrl, the qyl-owned telemetry names, typed Activity setter extensions, and the metric/span/event/entity definitions — plus the definition types themselves (MetricDefinition<TInstrument>, SpanDefinition<TKind>, EventDefinition, EntityDefinition, and their Stability/Deprecation/RequirementLevel/AttributeRef/EntityRef companions) |
.Incubating |
Attributes at every stability tier; Activities, Metrics, Spans, Events and Entities for the rows the stable package does not carry, under {Root}Incubating… type names; the qyl-owned instrument names; and Mapping.AttributeMapping — the collector's normalize table |
.Analyzers |
Roslyn diagnostics and code fixes for semantic-convention consumers, with a generated rule catalog and severity profiles |
dotnet add package Qyl.Telemetry.SemanticConventions
All three packages are published on
nuget.org; the package version is defined in
Directory.Build.props. Incubating APIs intentionally track
unstable upstream conventions and may change between minor releases.
Coming from Qyl.OpenTelemetry.SemanticConventions? These are new package IDs, not
new versions of the old ones. The Qyl.OpenTelemetry.SemanticConventions* IDs stop at
4.0.0 and receive no further releases; change to the Qyl.Telemetry.* family. The new
family began at 1.0.0 and now follows its own monotonic release line.
How the surface is generated
Weaver resolves the three registry layers itself and the Jinja templates under
templates/ emit the C# directly. There is no intermediate JSON and no
compile-time generator: the output is committed and CI checks it with git diff, the same
shape as the check-generated target in
opentelemetry-weaver-examples/basic.
registry/ (manifest.yaml: core + genai dependencies; qyl/ and vendor/ next to them)
|
v
scripts/generate.sh -> weaver registry generate --v2 --include-unreferenced
|
+----> src/Qyl.Telemetry.SemanticConventions/Generated/ (stable tier)
+----> src/Qyl.Telemetry.SemanticConventions.Incubating/Generated/ (the other tiers)
+----> src/…Analyzers/SemconvRegistryFacts.g.cs, SemconvDeprecations.g.cs
+----> generated/pins.props (the pins, for MSBuild)
+----> DocsGenerator ------------------------> analyzer documentation
Each package's Generated/ directory holds one file per registry root for six kinds:
Attributes, Activities, Metrics, Spans, Events and Entities. Attributes is the
one kind both packages carry in full: the stable package the stable rows plus the deprecated
migration symbols, the incubating package every key, at the byte-identical shape the
collector reads by reflection. For the other five the two packages are disjoint. The stable
package carries the stable and deprecated rows as {Root}ActivityExtensions,
{Root}MetricDefinitions and siblings; the incubating package carries only the rows the
stable package does not, as {Root}IncubatingActivityExtensions,
{Root}IncubatingMetricDefinitions and siblings, so a consumer may using both namespaces
without an ambiguous-call error. A registry root with no non-stable rows gets no incubating
type at all. A definition generated in either package is an instance of the same public type,
so it can be handed between libraries and applications.
Two gates keep the committed output honest. scripts/check-generated.sh regenerates
everything with the pinned Weaver and fails on git diff; CI runs it before the build.
GeneratedSurfaceTests pins the SHA-256 of every generated file, so a mismatch names each
differing, missing or extra one — only REGEN_SNAPSHOTS rewrites it.
Because the resolved v2 registry flattens registry.* groups into the catalog and drops
their group annotations, scripts/generate.sh reads the two lists that live only in
annotations — the scope names qyl constructs and the vendor ActivitySource names — out of
the same YAML and hands them to the templates as parameters. registry/ stays the only
source.
No template parameter has a default. The three schema URLs are registry facts the filters
read off the materialized registry itself; the Weaver version, the core tag, the core commit
and the genai commit reach the templates only from Version.props and
registry/manifest.yaml, through scripts/generate.sh. A bare weaver registry generate
therefore writes error: missing param <name> into the header instead of a stale pin, and
scripts/check-generated.sh fails on it.
Registry policies
The guards the Python merge used to carry are Rego. registry/policies
runs against the plain resolved shape, the only one that keeps group annotations: every
attribute qyl declares is in qyl.*, and every vendor group has its metadata sibling naming
the library, version, repository, ref, licence and ActivitySources, with a file-and-line
note on every attribute. registry/policies-v2 runs against the
materialized v2 registry, the only one that carries the full dependency catalog:
qyl.attribute.namespace enumerates every root namespace plus other, there is exactly one
GenAI token-usage metric and exactly one unconstrained execute_tool span, and every GenAI
any attribute carries a JSON Schema annotation.
Vendor models
registry/vendor/ owns one more thing than qyl's own vocabulary: the keys
a pinned third-party library emits on its own ActivitySource or Meter and that upstream
semantic conventions do not define. The collector's attribute allowlist is generated
from the registry, so a key nothing declares is dropped at ingest — which is exactly
what happens the moment an application stops wrapping a library and subscribes to its
native source instead.
A policy refuses any attribute outside qyl.* in the qyl group. There is no prefix
allowlist: one file per library names the library, the exact version qyl pins, the repository
and tag its attributes were read at, the licence, and the ActivitySource names it emits on
— and every attribute in it carries the file and line of the library that sets the key. A
vendor file that cannot answer those questions fails weaver registry check. Vendor rows are
development stability and are identified by their registry provenance path.
The ActivitySource names themselves are registry facts too: they ride as vendor annotations,
ship as QylTelemetryNames.VendorActivitySources, and join QYL0200's allowlist, so
AddSource and a span processor's source match need no literal.
Vendor keys are tags. The application never renames one and the collector passes it through:
Incubating.Mapping.AttributeMapping.IsVendorPassThrough is that list, next to
TryGetRename (every deprecated key resolved transitively to its final live replacement) and
NamespaceOf (the closed namespace set the dropped-attribute counter is broken down by).
This registry carries telemetry vocabulary only. Qyl's client-visible product requests,
responses, stream events, and errors remain owned by
qyl-api-schema.
Checking live telemetry against this registry
weaver registry live-check compares emitted spans, metrics and logs against the registry
and reports a finding per attribute. Its default levels are written for a registry that owns
everything it sees, which qyl's is not: qyl subscribes to native ActivitySources, so most
findings are about keys a pinned library emits and the collector already handles. The
registry therefore ships the policy set that says what the collector does with each one —
registry/policies/live_check_advice and
registry/.weaver.toml — and every consumer runs live-check with
both.
weaver registry live-check \
-r registry --include-unreferenced \
--config registry/.weaver.toml \
--advice-policies registry/policies/live_check_advice \
--input-source spans.json --fail-on violation
Three rules, each decided from the registry entry alone — there is no attribute-key list anywhere in the policy:
| finding | level | why |
|---|---|---|
open_enum_value |
information | The enum carries the member _OTHER, so it is open and a value outside the member list is what the specification prescribes. error.type is the case that matters: exception type names and status codes are all undocumented values of an open enum. |
undocumented_enum_value |
information | The same on a closed enum. Weaver's default level, kept. |
deprecated_renamed |
improvement | AttributeMapping.TryGetRename rewrites the key to its final live replacement. |
deprecated_obsoleted |
improvement | AttributeMapping.IsObsoleted tells the collector to drop the key and count the drop. |
deprecated_uncategorized |
violation | The registry names no replacement and the collector has no rule. Weaver's default level, kept. |
type_coercible |
improvement | The value parses as the declared type, so the collector coerces it. |
type_not_coercible |
violation | It does not. Weaver's default level, kept. |
enum_type_invalid |
violation | An enum sample that is neither string nor int. Weaver's default level, kept. |
Everything else is Weaver's, unchanged, including missing_attribute, not_stable, the
required/recommended/opt-in findings and the four name and namespace rules that
otel.rego — Weaver's own default policy,
copied verbatim into the set — carries.
Both flags are required. --advice-policies replaces the rego advisors only: Weaver's
deprecated, stability, type and enum advisors are compiled into the binary, always run, and
emit at a level no policy can change. registry/.weaver.toml drops the three findings the
qyl rules replace, by finding id and never by attribute name. Run with --advice-policies
alone and each of those findings is reported twice, once at Weaver's level and once at qyl's,
and --fail-on violation fails on telemetry qyl handles correctly.
scripts/check-live-check-policies.sh pins both
halves: it asserts the exact findings per attribute over
a sample covering every rule, and asserts that
dropping --config brings the built-in violations back.
Consuming the registry from another repository
All three of -r, --config and --advice-policies need a local path here. Weaver's
<url>[sub-folder] archive syntax does not work for this registry, and the reason is in
registry/manifest.yaml: the core dependency is a local filtered
copy at .build/core-filtered/model, which only
scripts/fetch-core.sh materialises. Pointing -r at
…/archive/refs/tags/v9.1.0.zip[registry] fails with
IO error for operation on .build/core-filtered/model. --advice-policies and --config do
not accept a URL at all — and --advice-policies fails silently on a path it cannot read,
loading no policies and leaving only the built-in advisors, so a typo there looks like a
registry that suddenly disagrees with itself.
The working recipe is to fetch the tag and materialise the core copy once:
curl -sSLo semconv.zip \
https://github.com/ANcpLua/Qyl.OpenTelemetry.SemanticConventions/archive/refs/tags/v9.1.0.zip
unzip -q semconv.zip # -> Qyl.OpenTelemetry.SemanticConventions-9.1.0/
cd Qyl.OpenTelemetry.SemanticConventions-9.1.0
./scripts/fetch-core.sh # writes .build/core-filtered/model
weaver registry live-check \
-r registry --include-unreferenced \
--config registry/.weaver.toml \
--advice-policies registry/policies/live_check_advice \
--input-source ../spans.json --fail-on violation
git clone --depth 1 --branch v9.1.0 followed by ./scripts/fetch-core.sh is equivalent and
is what Qyl.OpenTelemetry.AutoInstrumentation's live-check workflow does, with
actions/checkout into .semconv.
Analyzer documentation
The analyzer project exposes a generated rule catalog and ships as the third released
package; eng/release/verify-packages.sh proves it installs into a clean consumer
alongside the other two.
The generated analyzer reference includes the
index,
migration catalog, and
per-rule pages. Consumer severity can be configured through
OtelSemConvAnalysisMode:
<PropertyGroup>
<OtelSemConvAnalysisMode>AllAsErrors</OtelSemConvAnalysisMode>
</PropertyGroup>
Supported values are Default, AllAsErrors, and Disabled. If the property is
unset, the consumer's editorconfig remains authoritative.
QYL0008 in instrumentation libraries
QYL0008 flags a direct reference to
an *.SemanticConventions.Incubating member from a library project, because the library
would then pin every downstream consumer to its exact package version. Copying the value
into the library is the mitigation, and the analyzer stays silent for all three copy
forms plus a method-local const:
private const string MessagingSystem = MessagingAttributes.System;
private static readonly string OperationType = MessagingAttributes.OperationType;
private static readonly string[] Copies = [MessagingAttributes.OperationName];
public static void Tag(Activity activity)
{
const string destination = MessagingAttributes.DestinationName;
activity.SetTag(destination, "orders");
}
An instrumentation library that deliberately version-locks with the incubating tier —
Qyl.Telemetry.AutoInstrumentation ships in lockstep with this package family — opts the
whole project out instead of copying every constant:
<Project>
<PropertyGroup>
<OtelSemConvInstrumentationLibrary>true</OtelSemConvInstrumentationLibrary>
</PropertyGroup>
</Project>
The property is opt-in and per-project; QYL0008 keeps reporting everywhere it is unset.
Build and test
weaver registry check -r registry
./scripts/check-generated.sh # regenerates from registry/ and fails on drift
./scripts/check-live-check-policies.sh # pins the findings the advice policies produce
dotnet build Qyl.Telemetry.SemanticConventions.slnx -c Release
dotnet run --project tests/Qyl.Telemetry.SemanticConventions.Pipeline.Tests -c Release
python3 -m unittest discover --start-directory tests/scripts --pattern 'test_*.py'
weaver must be the version Version.props pins; scripts/generate.sh
refuses to run against any other. dotnet test does not drive these projects: they are
Microsoft.Testing.Platform projects and the .NET 10 SDK dropped the VSTest bridge, so the
runner is dotnet run --project <test project>, which is what CI uses.
Publishing uses GitHub Actions OIDC trusted publishing. No long-lived NuGet API key is stored in the repository.
License
Apache-2.0
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Diagnostics.DiagnosticSource (>= 10.0.11)
-
net10.0
- No dependencies.
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Qyl.Telemetry.SemanticConventions:
| Package | Downloads |
|---|---|
|
Qyl.Telemetry.SemanticConventions.Incubating
OpenTelemetry semantic-conventions incubating surface, generated by Weaver from the qyl registry (registry/manifest.yaml) and shipped pre-built: every stability tier of the attribute keys, the typed Activity setter extensions, the first-class metric/span/event/entity definitions, the qyl-owned instrument names, and the collector's attribute mapping table. These keys are subject to breaking changes between minor versions — opt in deliberately. |
|
|
Qyl.Telemetry.AutoInstrumentation
Managed .NET 10 and NativeAOT instrumentation using Roslyn interceptors, Activity/Meter primitives, and public runtime hooks. No CLR profiler or runtime IL rewriting. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 9.4.0 | 297 | 9/11/2026 |
| 9.3.1 | 49 | 9/11/2026 |
| 9.3.0 | 1,894 | 9/7/2026 |
| 9.2.0 | 636 | 9/7/2026 |
| 9.1.0 | 414 | 9/7/2026 |
| 9.0.0 | 251 | 9/7/2026 |
| 8.1.0 | 433 | 9/4/2026 |
| 8.0.1 | 430 | 9/4/2026 |
| 8.0.0 | 447 | 9/3/2026 |
| 7.1.1 | 409 | 9/2/2026 |
| 7.1.0 | 103 | 9/2/2026 |
| 7.0.0 | 437 | 9/2/2026 |
| 6.0.0 | 286 | 8/28/2026 |
| 5.2.0 | 110 | 8/22/2026 |
| 5.1.0 | 97 | 8/22/2026 |
| 5.0.0 | 94 | 8/21/2026 |
| 4.5.0 | 97 | 8/21/2026 |
| 4.4.0 | 1,098 | 8/21/2026 |
| 4.3.0 | 379 | 8/20/2026 |
| 4.2.0 | 269 | 8/14/2026 |