-
Notifications
You must be signed in to change notification settings - Fork 3
Generated Output
This page shows what code the Purview Telemetry Source Generator creates from your interface definitions. All examples are taken from the SampleApp.APIService project in this repository with EmitCompilerGeneratedFiles enabled.
The following multi-target interface (IEntityStoreTelemetry) is the source for all generated output shown on this page:
using System.Diagnostics;
using Purview.Telemetry;
[ActivitySource]
[Logger]
[Meter]
interface IEntityStoreTelemetry
{
[Activity]
[Info]
[AutoCounter]
Activity? GettingEntityFromStore(int entityId, [Baggage] string serviceUrl);
[Event]
[Trace]
void GetDuration(Activity? activity, int durationInMS);
[Context]
void RetrievedEntity(Activity? activity, float totalValue, int lastUpdatedByUserId);
[Warning]
void EntityNotFound(int entityId);
[Histogram]
void RecordEntitySize(int sizeInBytes);
}Generated files appear in obj/Debug|Release/net*/generated/Purview.Telemetry.SourceGenerator/ when EmitCompilerGeneratedFiles is enabled.
File: EntityStoreTelemetryCore.Activity.g.cs
[EditorBrowsable(EditorBrowsableState.Never)]
[ExcludeFromCodeCoverage]
[GeneratedCode("Purview.Telemetry.SourceGenerator", "...")]
sealed partial class EntityStoreTelemetryCore : global::IEntityStoreTelemetry
{
readonly static global::System.Diagnostics.ActivitySource _activitySource =
new("sample-weather-app-api");
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private global::System.Diagnostics.Activity? GettingEntityFromStore_Activity(
int entityId, string serviceUrl)
{
if (!_activitySource.HasListeners())
return null;
global::System.Diagnostics.Activity? activity = _activitySource.StartActivity(
"GettingEntityFromStore", ActivityKind.Internal,
parentId: default, tags: default, links: default, startTime: default);
if (activity != null)
{
activity.SetTag("entity_id", entityId);
activity.SetBaggage("service_url", serviceUrl);
}
return activity;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GetDuration_Activity(Activity? activity, int durationInMS)
{
if (!_activitySource.HasListeners())
return;
if (activity != null)
{
var tagsCollection = new ActivityTagsCollection();
tagsCollection.Add("duration_in_ms", durationInMS);
activity.AddEvent(new ActivityEvent(
name: "GetDuration", timestamp: default, tags: tagsCollection));
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RetrievedEntity(Activity? activity, float totalValue, int lastUpdatedByUserId)
{
if (!_activitySource.HasListeners())
return;
if (activity != null)
{
activity.SetTag("total_value", totalValue);
activity.SetTag("last_updated_by_user_id", lastUpdatedByUserId);
}
}
}
[Context]methods are emitted directly as public methods (no private helper) because they have no logging or metrics target and can short-circuit immediately onHasListeners().
File: EntityStoreTelemetryCore.Logging.g.cs
Uses the v1 (LoggerMessage.Define) pattern (v2 requires Microsoft.Extensions.Telemetry.Abstractions):
sealed partial class EntityStoreTelemetryCore : global::IEntityStoreTelemetry
{
readonly global::Microsoft.Extensions.Logging.ILogger<global::IEntityStoreTelemetry> _logger;
static readonly Action<ILogger, int, string, Exception?> _gettingEntityFromStoreAction =
LoggerMessage.Define<int, string>(
LogLevel.Information,
new EventId(106573457, "GettingEntityFromStore"),
"GettingEntityFromStore: EntityId = {EntityId}, ServiceUrl = {ServiceUrl}");
static readonly Action<ILogger, int, Exception?> _getDurationAction =
LoggerMessage.Define<int>(
LogLevel.Trace,
new EventId(2132566653, "GetDuration"),
"GetDuration: DurationInMS = {DurationInMS}");
static readonly Action<ILogger, int, Exception?> _entityNotFoundAction =
LoggerMessage.Define<int>(
LogLevel.Warning,
new EventId(173845223, "EntityNotFound"),
"EntityNotFound: EntityId = {EntityId}");
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GettingEntityFromStore_Logging(int entityId, string serviceUrl)
{
if (!_logger.IsEnabled(LogLevel.Information))
return;
_gettingEntityFromStoreAction(_logger, entityId, serviceUrl, null);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GetDuration_Logging(int durationInMS)
{
if (!_logger.IsEnabled(LogLevel.Trace))
return;
_getDurationAction(_logger, durationInMS, null);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void EntityNotFound(int entityId)
{
if (!_logger.IsEnabled(LogLevel.Warning))
return;
_entityNotFoundAction(_logger, entityId, null);
}
}Log-only methods (
[Warning] void EntityNotFound(...)) are emitted directly as public methods without a private helper.
File: EntityStoreTelemetryCore.Metric.g.cs
sealed partial class EntityStoreTelemetryCore : global::IEntityStoreTelemetry
{
global::System.Diagnostics.Metrics.Meter _meter = default!;
global::System.Diagnostics.Metrics.Counter<int> _gettingEntityFromStoreInstrument = default!;
global::System.Diagnostics.Metrics.Histogram<int> _recordEntitySizeInstrument = default!;
void InitializeMeters(IMeterFactory meterFactory)
{
if (_meter != null)
throw new Exception("The meters have already been initialized.");
var meterTags = new Dictionary<string, object?>();
PopulateMeterTags(meterTags);
_meter = meterFactory.Create(new MeterOptions("SampleApp.APIService")
{
Version = null,
Tags = meterTags
});
var counterTags = new Dictionary<string, object?>();
PopulateGettingEntityFromStoreTags(counterTags);
_gettingEntityFromStoreInstrument = _meter.CreateCounter<int>(
"entity_store.getting_entity_from_store", unit: null,
description: null, tags: counterTags);
var histTags = new Dictionary<string, object?>();
PopulateRecordEntitySizeTags(histTags);
_recordEntitySizeInstrument = _meter.CreateHistogram<int>(
"entity_store.record_entity_size", unit: null,
description: null, tags: histTags);
}
partial void PopulateMeterTags(Dictionary<string, object?> meterTags);
partial void PopulateGettingEntityFromStoreTags(Dictionary<string, object?> instrumentTags);
partial void PopulateRecordEntitySizeTags(Dictionary<string, object?> instrumentTags);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GettingEntityFromStore_Metrics(int entityId, string serviceUrl)
{
_gettingEntityFromStoreInstrument.Add(1,
new KeyValuePair<string, object?>("entity_id", entityId),
new KeyValuePair<string, object?>("service_url", serviceUrl));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RecordEntitySize(int sizeInBytes)
{
_recordEntitySizeInstrument.Record(sizeInBytes);
}
}Metric-only methods (
[Histogram] void RecordEntitySize(...)) are emitted as public methods directly. The partialPopulate*Tagsmethods let you add static per-instrument tags at startup.
For multi-target methods, a public method is generated that calls the per-target private helpers:
sealed partial class EntityStoreTelemetryCore : global::IEntityStoreTelemetry
{
// Multi-target: Activity + Logging + Metrics
public Activity? GettingEntityFromStore(int entityId, string serviceUrl)
{
var activityResult = GettingEntityFromStore_Activity(entityId, serviceUrl);
GettingEntityFromStore_Logging(entityId, serviceUrl);
GettingEntityFromStore_Metrics(entityId, serviceUrl);
return activityResult;
}
// Multi-target: ActivityEvent + Logging
public void GetDuration(Activity? activity, int durationInMS)
{
GetDuration_Activity(activity, durationInMS);
GetDuration_Logging(durationInMS);
}
}File: EntityStoreTelemetryCoreDIExtension.DependencyInjection.g.cs
namespace Microsoft.Extensions.DependencyInjection
{
[EditorBrowsable(EditorBrowsableState.Never)]
[ExcludeFromCodeCoverage]
[GeneratedCode("Purview.Telemetry.SourceGenerator", "...")]
static class EntityStoreTelemetryCoreDIExtension
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IServiceCollection AddEntityStoreTelemetry(
this IServiceCollection services)
{
return services.AddSingleton<global::IEntityStoreTelemetry,
global::EntityStoreTelemetryCore>();
}
}
}Register with:
builder.Services.AddEntityStoreTelemetry();The generated constructor accepts ILogger<IEntityStoreTelemetry> and IMeterFactory, injected automatically.
File: SampleApp.APIService.TelemetryNames.g.cs
A static class listing all ActivitySource and Meter names used by the assembly — useful for OpenTelemetry configuration:
namespace SampleApp.APIService
{
[EditorBrowsable(EditorBrowsableState.Never)]
[ExcludeFromCodeCoverage]
[GeneratedCode("Purview.Telemetry.SourceGenerator", "...")]
static class TelemetryNames
{
public static readonly string[] MeterNames = new string[]
{
"SampleApp.APIService"
};
public static readonly string[] ActivitySourceNames = new string[]
{
"sample-weather-app-api"
};
}
}Use these names when configuring OpenTelemetry exporters:
builder.Services.AddOpenTelemetry()
.WithTracing(t => {
foreach (var name in SampleApp.APIService.TelemetryNames.ActivitySourceNames)
t.AddSource(name);
})
.WithMetrics(m => {
foreach (var name in SampleApp.APIService.TelemetryNames.MeterNames)
m.AddMeter(name);
});Important
Consider helping children around the world affected by conflict. You can donate any amount to War Child here - any amount can help save a life.
Purview Telemetry Source Generator v4.0.0-prerelease.1 | Home | Getting Started | FAQ | Breaking Changes | GitHub