AutoInstrument 1.1.1

dotnet add package AutoInstrument --version 1.1.1
                    
NuGet\Install-Package AutoInstrument -Version 1.1.1
                    
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="AutoInstrument" Version="1.1.1">
  <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="AutoInstrument" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="AutoInstrument">
  <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 AutoInstrument --version 1.1.1
                    
#r "nuget: AutoInstrument, 1.1.1"
                    
#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 AutoInstrument@1.1.1
                    
#: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=AutoInstrument&version=1.1.1
                    
Install as a Cake Addin
#tool nuget:?package=AutoInstrument&version=1.1.1
                    
Install as a Cake Tool

AutoInstrument

[Instrument] for .NET - add an attribute, get OpenTelemetry spans with tagged parameters at every call-site. Inspired by Rust's #[instrument].

[Instrument]
public async Task<string> ShaveYak(int yakId, string style)
{
    await Task.Delay(50);
    return $"Yak #{yakId} shaved with {style}";
}

Under the hood, the source generator emits C# interceptors that wrap each call-site with an Activity, tag parameters, and record exceptions. Your method is never modified.

Setup

Add the package and enable interceptors:

<PropertyGroup>
  <InterceptorsNamespaces>$(InterceptorsNamespaces);AutoInstrument.Generated</InterceptorsNamespaces>
</PropertyGroup>
using AutoInstrument;

[Instrument]
public async Task<Order> ProcessOrder(int orderId, string customer) { ... }

[Instrument(Skip = new[] { "creditCard" })]
public async Task ChargeCustomer(int orderId, string creditCard) { ... }

[Instrument(Name = "orders.compute_total", RecordReturnValue = true)]
public decimal ComputeTotal(List<LineItem> items) => items.Sum(i => i.Price * i.Quantity);

Options

Property Default Description
Name Class.Method Span name
Skip Parameters/properties to exclude from tags
Fields Whitelist -D only these become tags
ActivitySourceName Assembly name Custom ActivitySource name
RecordReturnValue false Tag the return value
RecordException true Record exceptions on the span
Kind 0 (Internal) ActivityKind (0=Internal, 1=Server, 2=Client, 3=Producer, 4=Consumer)
RecordSuccess false Set status Ok on success
IgnoreCancellation true Don't record OperationCanceledException as errors
Condition Boolean member name - skip instrumentation when false
LinkTo Parameter name (must be ActivityContext) to attach as ActivityLink
Depth Global default (1) Max depth for expanding complex type properties

Skip and Fields support dot-notation at any depth: Skip = new[] { "order.Address.City" }.

Parameter attributes

[NoInstrument] on a parameter skips it from tagging. Pass property names to skip specific properties of a complex type:

public void Login(string user, [NoInstrument] string password) { ... }

public void Process([NoInstrument("CreditCard", "SSN")] Order order) { ... }

Member tags

[Tag] on a field or property includes it as a span tag on all [Instrument] methods in the class:

public class OrderService
{
    [Tag] public string Region { get; set; }
    [Tag(Name = "env")] public string Environment { get; set; }

    [Instrument]
    public void Process(int orderId) { ... }
    // Tags: process.orderid, region, env
}

Complex types are expanded recursively, just like method parameters. Use Skip, Fields, or Depth to control expansion:

public class OrderService
{
    [Tag(Skip = new[] { "Secret" })] public Config Settings { get; set; }
    [Tag(Fields = new[] { "Region" })] public Config Backup { get; set; }
    [Tag(Depth = 1)] public Config Shallow { get; set; }
    // Settings → settings.region, settings.timeout (Secret excluded)
    // Backup   → backup.region (only Region included)
    // Shallow  → one level only
}

Complex types

Classes and structs are expanded one level deep by default. Dot-notation in Skip or Fields automatically resolves deeper — no need to increase Depth manually:

[Instrument]
public void Process(Order order) { ... }
// Tags: process.order.id, process.order.address (1 level deep)

[Instrument(Fields = new[] { "order.Address.City" })]
public void Targeted(Order order) { ... }
// Tags: process.order.address.city (auto-resolved to reach City)

[Instrument(Depth = 3)]
public void Deep(Order order) { ... }
// Tags: process.order.id, process.order.address.city, process.order.address.zip (fully expanded)

Circular references are detected and stopped automatically. Collections (arrays, List<T>, etc.) are not expanded — they are tagged as-is.

Configuration

The ActivitySource name defaults to the assembly name. Override at three levels (highest priority wins):

  1. Per-method: [Instrument(ActivitySourceName = "X")]
  2. MSBuild: <AutoInstrumentSourceName>X</AutoInstrumentSourceName>
  3. Assembly attribute: [assembly: AutoInstrumentSource("X")]

Tag naming defaults to methodname.param. Set it to Flat for just param:

[assembly: AutoInstrumentConfig(TagNaming = TagNamingConvention.Flat)]

Or via MSBuild: <AutoInstrumentTagNaming>Flat</AutoInstrumentTagNaming>

The default expansion depth is 1. Dot-notation in Skip/Fields auto-resolves deeper. Override globally:

[assembly: AutoInstrumentConfig(Depth = 2)]

Or via MSBuild: <AutoInstrumentDepth>2</AutoInstrumentDepth>

Diagnostics

ID Description
AUTOINST001 Skip references unknown parameter
AUTOINST002 Fields references unknown parameter
AUTOINST003 Dot-notation references unknown property
AUTOINST004 Condition is not a boolean member
AUTOINST005 LinkTo is not an ActivityContext parameter
AUTOINST006 [NoInstrument] references unknown property
AUTOINST007 [Tag] Skip references unknown property
AUTOINST008 [Tag] Fields references unknown property

Limitations

  • Interceptors only work within the same compilation — cross-project calls aren't intercepted.
  • Recursive calls create nested spans.
  • Complex types expand up to the configured depth (default 1). Dot-notation auto-resolves deeper. Collections are not expanded.

Requirements

.NET 10

License

MIT

Product 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 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

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
1.1.1 115 2/24/2026
1.1.0 99 2/24/2026
1.0.0 107 2/24/2026
0.1.1 101 2/24/2026
0.1.0 102 2/23/2026

### Documentation

- update comments in InstrumentAttribute for clarity
- update README for improved clarity and structure

### Features

- add initial project files and configuration for AutoInstrument
- add diagnostic analyzer for InstrumentAttribute validation
- add support for dot-notation property validation
- add README section for attribute options and validation rules
- add tagging and instrumentation attributes for enhanced tracing
- add new sample projects and services for AspireSample API
- add new project GUID for enhanced instrumentation
- add support for complex types in Tag attribute
- add Depth property for complex type expansion control
- implement tag filtering and formatting logic
- add PackageTags and PackageReleaseNotes for better metadata
- update release notes generation and add GitHub release step

### Miscellaneous

- update packaging and push commands for AutoInstrument
- include README.md in package for better documentation access
- update package references for improved compatibility
- update Microsoft.Extensions.Http.Resilience package to version 10.3.0

### Refactor

- remove commented-out code for clarity
- simplify XML documentation for clarity