AutoInstrument 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package AutoInstrument --version 1.0.0
                    
NuGet\Install-Package AutoInstrument -Version 1.0.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="AutoInstrument" Version="1.0.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="AutoInstrument" Version="1.0.0" />
                    
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.0.0
                    
#r "nuget: AutoInstrument, 1.0.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 AutoInstrument@1.0.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=AutoInstrument&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=AutoInstrument&version=1.0.0
                    
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 - 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

Skip and Fields support dot-notation for complex type properties: Skip = new[] { "order.CreditCard" }.

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

Classes and structs are expanded one level deep into their public properties:

[Instrument]
public void Process(Order order, int priority) { ... }
// Tags: process.order.id, process.order.customer, process.order.creditcard, process.priority

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>

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

Limitations

  • Interceptors only work within the same compilation — cross-project calls aren't intercepted.
  • Recursive calls create nested spans.
  • Complex types expand one level deep only.

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