Qyl.Telemetry.SemanticConventions.SourceGeneration 7.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Qyl.Telemetry.SemanticConventions.SourceGeneration --version 7.1.0
                    
NuGet\Install-Package Qyl.Telemetry.SemanticConventions.SourceGeneration -Version 7.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Qyl.Telemetry.SemanticConventions.SourceGeneration" Version="7.1.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Qyl.Telemetry.SemanticConventions.SourceGeneration" Version="7.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Qyl.Telemetry.SemanticConventions.SourceGeneration">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Qyl.Telemetry.SemanticConventions.SourceGeneration --version 7.1.0
                    
#r "nuget: Qyl.Telemetry.SemanticConventions.SourceGeneration, 7.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Qyl.Telemetry.SemanticConventions.SourceGeneration@7.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Qyl.Telemetry.SemanticConventions.SourceGeneration&version=7.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Qyl.Telemetry.SemanticConventions.SourceGeneration&version=7.1.0
                    
Install as a Cake Tool

Qyl.Telemetry.SemanticConventions.SourceGeneration

Roslyn source generator for OpenTelemetry semantic-convention constants, first-class definitions, and thin helper APIs. It does not collect telemetry. Consumers own their Meter, ActivitySource, Logger, instrumentation scope, versioning, and enablement.

When to use this package

This is the application-side consumption mode: the generator emits only the declared groups into your own assembly, with internal visibility and nothing you did not ask for. Libraries that need one pinned registry version across a package family (for example Qyl.Telemetry.AutoInstrumentation) reference the compiled Qyl.Telemetry.SemanticConventions packages instead; see the repository README's "Choosing between the compiled packages and the source generator" section.

The definition surfaces (metrics, spans, events, entities) are typed against Qyl.Telemetry.SemanticConventions, the one home of MetricDefinition<TInstrument>, SpanDefinition<TKind>, EventDefinition, EntityDefinition, Stability, Deprecation, RequirementLevel, AttributeRef, EntityRef, and the instrument/span-kind marker structs. Reference that package next to the generator; a compilation that declares a definition marker without it gets QYLSG001 at the marker instead of generated source. The attribute-constant and Activity setter surfaces have no runtime package dependency.

<ItemGroup>
  <PackageReference Include="Qyl.Telemetry.SemanticConventions" Version="..." />
  <PackageReference Include="Qyl.Telemetry.SemanticConventions.SourceGeneration" Version="..."
                    OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

Use

using Qyl.Telemetry.SemanticConventions.SourceGeneration;

[SemanticConventionAttributes("http")]
internal static partial class HttpAttributes;

[SemanticConventionIncubatingAttributes("http")]
internal static partial class HttpIncubatingAttributes;

[SemanticConventionActivities("http")]
internal static partial class HttpActivityExtensions;

[SemanticConventionMetricDefinitions("http.server")]
internal static partial class HttpServerMetrics;

[SemanticConventionSpanDefinitions("http")]
internal static partial class HttpSpans;

[SemanticConventionIncubatingEventDefinitions("app")]
internal static partial class AppEvents;

[SemanticConventionIncubatingEntityDefinitions("host")]
internal static partial class HostEntities;

// Generated:
//   public const string AttributeHttpRequestMethod = "http.request.method";
//   public static Activity SetHttpRoute(this Activity activity, string value)
//   public static readonly MetricDefinition<Histogram> HttpServerRequestDuration = new(name: "http.server.request.duration", ...);
//   public static readonly SpanDefinition<Server> HttpServer = new(id: "http.server", ...);
//   public static readonly EventDefinition AppCrash = new(name: "app.crash", ...);
//   public static readonly EntityDefinition Host = new(name: "host", ...);

Generator surfaces

Every generator uses the same Roslyn shape (GeneratorPipeline): publish its stable and incubating marker attributes during post-initialization, discover annotated partial classes with ForAttributeWithMetadataName, extract the requested semantic-convention prefix into a marker model, then emit source from the matching registry projection.

Surface Marker attributes Registry projection Emitter Generated shape
Attributes SemanticConventionAttributes, SemanticConventionIncubatingAttributes RegistryLoader.Registry AttributesEmitter Attribute-key constants and enum-value helper classes (contrib member shape, plus the value set below).
Activities SemanticConventionActivities, SemanticConventionIncubatingActivities ActivityRegistryLoader.Registry ActivityExtensionsEmitter Activity extension methods that set typed semantic tags, with the same enum-value classes.
Metric definitions SemanticConventionMetricDefinitions, SemanticConventionIncubatingMetricDefinitions RegistryLoader.Instruments MetricDefinitionsEmitter MetricDefinition<TInstrument> fields: name, unit, stability, deprecation, entity and attribute references.
Span definitions SemanticConventionSpanDefinitions, SemanticConventionIncubatingSpanDefinitions RegistryLoader.Signals SpanDefinitionsEmitter SpanDefinition<TKind> fields.
Event definitions SemanticConventionEventDefinitions, SemanticConventionIncubatingEventDefinitions RegistryLoader.Signals EventDefinitionsEmitter EventDefinition fields.
Entity definitions SemanticConventionEntityDefinitions, SemanticConventionIncubatingEntityDefinitions RegistryLoader.Signals EntityDefinitionsEmitter EntityDefinition fields with describing/identifying attribute references.

Enum value sets

Every generated …Values class, in the package projection and in both consumer projections, ends with the vocabulary-owned value set so consumers validate against the registry instead of retyping it:

/// <summary>Every catalogued value, in registry order.</summary>
public static global::System.Collections.Generic.IReadOnlyList<string> AllValues { get; } = new[] { "CONNECT", "DELETE", "GET", /* … */ };
/// <summary>Whether <paramref name="value"/> is a catalogued value (ordinal).</summary>
public static bool Contains(string value) { /* ordinal scan of AllValues */ }

AllValues follows the constants' order and stability filter of its projection (registry order in the consumer projections, identifier order in the package projection; deprecated members are included exactly when their constants are). The initializer holds string literals, so a deprecated constant never raises CS0618, and it is netstandard2.0-plain (no LINQ, no collection expressions). The property is AllValues rather than All because cassandra.consistency.level declares a constant All; the emitter fails generation if a registry member ever collides with AllValues or Contains.

Free-form attributes have no value set

An attribute the registry types as a plain string has no …Values class, and qyl will not add one. messaging.operation.name is the standing case: upstream types it string with examples: ack, nack, send — a system-specific operation name deliberately left open — while the enumerated sibling is messaging.operation.type (create, send, receive, process, settle, plus the deprecated deliver/publish). qyl cannot enumerate messaging.operation.name even if it wanted to: the attribute is upstream-owned, and merge_registries.py refuses any qyl row outside the qyl.* namespace and any qyl row that shadows an upstream one, so a qyl-authored member list would either be rejected at merge time or fork the definition away from the schema URL the packages publish. Instrumentation therefore chooses its own messaging.operation.name values (send, publish, …) and validates only messaging.operation.type against MessagingAttributes.OperationTypeValues.AllValues. publish being a deprecated operation type says nothing about publish as an operation name, and the analyzers agree: QYL0012/QYL0013 and the deprecated-value analyzer key off the registry's enum members, so they never constrain a free-form string attribute.

Package projections

Three assembly-level markers project a whole registry tier in the layout the compiled packages ship, under the package root namespace they name. They take no prefix.

Marker Emits
[assembly: SemanticConventionAttributesPackage("<root>")] <root>.Attributes.{Root}.{Root}Attributes (public static class) for every registry root with a stable or deprecated row, plus <root>.SchemaUrl carrying the pinned schema URL.
[assembly: SemanticConventionIncubatingAttributesPackage("<root>")] <root>.Attributes.{Root}.{Root}Attributes for every registry root, all stability tiers.
[assembly: SemanticConventionTelemetryNamesPackage("<root>")] <root>.Names.QylTelemetryNames with the qyl-owned Scopes and Events constants. Declared by the stable package: the Qyl.Telemetry producer packages build their ActivitySource and Meter from these scope names and may not read the incubating tier.

Member names in the package layout drop the root segment (http.routeHttpAttributes.Route), unlike the contrib-shape class markers (AttributeHttpRoute). The projection is exactly how the Qyl.Telemetry.SemanticConventions and .Incubating packages are built: each package project references this generator as an analyzer and declares its markers in SemanticConventions.cs; the generator never references those packages.

[assembly: SemanticConventionAttributesPackage("Qyl.Telemetry.SemanticConventions")]
// Qyl.Telemetry.SemanticConventions.Attributes.Http.HttpAttributes.RequestMethod
// Qyl.Telemetry.SemanticConventions.SchemaUrl.Current

PackageProjectionTests pins the whole projection: five full-file byte-identity snapshots (http stable and incubating, qyl, QylTelemetryNames, SchemaUrl) — with QylTelemetryNames asserted in the stable projection and absent from the incubating one — and Snapshots/qyl.package.manifest.sha256, one <sha256> <hint name> line per file both projections emit; a mismatch names every differing, missing, and extra file, and only REGEN_SNAPSHOTS rewrites them. Doc comments are rendered from the registry's markdown into well-formed XML (PackageDocComments), and generated docs are compiled in DocumentationMode.Diagnose so a malformed comment fails the gate.

The marker attributes are generated into the consuming assembly via RegisterPostInitializationOutput as internal, [Conditional] attributes. The definition types are not generated: they are public types of Qyl.Telemetry.SemanticConventions, so definitions produced in different assemblies share one type family.

Stable markers emit stable rows plus deprecated migration symbols. Incubating markers are supersets: stable + development/alpha/beta/release-candidate + deprecated. This mirrors Java/Python's incubating package behavior and avoids breaking consumers when conventions are promoted.

Choose one projection per prefix in normal consumer code. Incubating is a superset, so declaring both stable and incubating activity helpers for the same prefix in the same namespace can make shared extension methods ambiguous. If a test fixture intentionally declares both, call the generated static helper class explicitly.

Diagnostics

ID Severity When
QYLSG001 Error A definition marker (*MetricDefinitions, *SpanDefinitions, *EventDefinitions, *EntityDefinitions) is declared in a compilation that does not reference Qyl.Telemetry.SemanticConventions.

Versioning

Tracks two upstream source registries plus the qyl-owned one:

Source Canonical pin Generated exact provenance
Core semantic conventions Version.props The core entry in resolved-registry.json
GenAI semantic conventions Version.props The genai entry in resolved-registry.json
qyl-owned vocabulary qyl-registry.json The qyl entry in resolved-registry.json: source_ref is the file, source_commit is the SHA-256 of its bytes

The upstream provenance entries carry the exact resolved ref, commit, and schema URL; they are regenerated from the canonical pins instead of copied into this document. The qyl entry, and every merged qyl row, carries source_ref: qyl-registry.json and source_commit = SHA-256 of that file's bytes, with schema_url and source_date_epoch as JSON null: qyl publishes no schema URL and has no upstream date.

The GenAI registry is development-stage. It is pinned by commit SHA and must not be presented as a stable v1.42.0 release.

The embedded registry is regenerated by scripts/generate.sh with the Weaver version pinned in Version.props; generation fails on a different binary. The script runs Weaver twice, once for core and once for GenAI, then scripts/merge_registries.py merges both projections and the qyl-owned registry with a dedup key per row kind (group id, attribute key, metric name, event name, entity id; the last source wins) while preserving per-row source metadata. Because the merge is last-wins, it refuses a qyl attribute outside the qyl.* namespace and any qyl attribute, metric, or metric group that shadows an upstream row, naming the offending key (tests/scripts/test_merge_registries.py covers the guard without Weaver). The core run excludes gen-ai, mcp, openai, and aws-bedrock, so those rows come only from the GenAI source. qyl attributes join the catalog, qyl metrics join metrics and groups with their attribute references resolved against the merged catalog, and the qyl scope and event names land at the root, so RegistryLoader and every other consumer see qyl.* with no special casing.

The merge also fingerprints every effective model file, preserves both manifests, and embeds every referenced GenAI JSON Schema. Two generated consumers share that same projection:

  • emit_registry_resources.py publishes the complete resolved registry and raw structured-payload schemas through the incubating package.
  • emit_analyzer_registry.py derives attribute types, enum spellings, GenAI/MCP span requirements, provider refinements, and metric names for the analyzer project.

Both scripts support --check; normal repository builds and CI fail when their committed outputs drift from resolved-registry.json. emit_typespec_keys.py projects the upstream keys for qyl-api-schema and deliberately excludes the qyl rows (qyl's public contracts change owner-first, not as a side effect of the merge); it writes no file in this repository, so it has no --check mode.

The generated member shape is snapshot-tested per stability tier on the repository's net10.0 test host. The release gate also restores the packed source generator into a clean net10.0 consumer, compiles generated members, and executes the result.

Licensed under Apache-2.0. Generated content is derived from the Apache-2.0 OpenTelemetry semantic-conventions registries.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.1.0 97 9/4/2026
8.0.1 100 9/4/2026
8.0.0 137 9/3/2026
7.1.1 134 9/2/2026
7.1.0 99 9/2/2026
7.0.0 142 9/2/2026
6.0.0 160 8/28/2026
5.2.0 136 8/22/2026
5.1.0 108 8/22/2026
5.0.0 101 8/21/2026
4.5.0 102 8/21/2026
4.4.0 428 8/21/2026
4.3.0 161 8/20/2026
4.2.0 169 8/14/2026
4.1.0 116 8/1/2026
1.0.0 431 7/27/2026