Production debugging agent for .NET applications that captures exceptions and context without stopping execution.
- .NET 6.0, 7.0, or 8.0
- Windows, Linux, or macOS
- Network connectivity to AIVory backend
Install via NuGet Package Manager:
dotnet add package AIVory.MonitorOr add to your .csproj:
<PackageReference Include="AIVory.Monitor" Version="1.0.0" />using AIVory.Monitor;
using Microsoft.Extensions.Logging;
// Initialize with configuration from environment variables
var config = AgentConfig.FromEnvironment();
var logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<AIVoryMonitorAgent>();
AIVoryMonitorAgent.Init(config, logger);
// Agent will now automatically capture unhandled exceptions
// and gracefully shutdown on process exitAdd the middleware to your ASP.NET Core application:
using AIVory.Monitor;
var builder = WebApplication.CreateBuilder(args);
// Initialize agent
var config = AgentConfig.FromEnvironment();
AIVoryMonitorAgent.Init(config, builder.Logging.CreateLogger<AIVoryMonitorAgent>());
var app = builder.Build();
// Add AIVory monitoring middleware (captures request context)
app.UseAIVoryMonitor();
app.MapGet("/", () => "Hello World!");
app.Run();The middleware automatically captures:
- HTTP request details (method, path, query, headers)
- User identity (if authenticated)
- Request timing
- Exception context correlation
Capture exceptions explicitly without rethrowing:
try
{
// Your code
}
catch (Exception ex)
{
var context = new Dictionary<string, object>
{
{ "userId", currentUser.Id },
{ "operation", "ProcessOrder" }
};
AIVoryMonitorAgent.Instance.CaptureException(ex, context);
// Handle exception gracefully
}Capture exception details and rethrow:
try
{
// Your code
}
catch (Exception ex)
{
var context = new Dictionary<string, object>
{
{ "orderId", order.Id }
};
AIVoryMonitorAgent.Instance.CaptureAndRethrow(ex, context);
}Use the fluent extension method on exceptions:
try
{
// Your code
}
catch (Exception ex)
{
var context = new Dictionary<string, object>
{
{ "userId", userId },
{ "timestamp", DateTime.UtcNow }
};
ex.CaptureWithAIVory(context);
throw;
}Configure the agent via environment variables or programmatically.
| Variable | Description | Default |
|---|---|---|
AIVORY_API_KEY |
Authentication key (required) | - |
AIVORY_BACKEND_URL |
Backend WebSocket URL | wss://api.aivory.net |
AIVORY_ENVIRONMENT |
Environment name (dev, staging, prod) | production |
AIVORY_SAMPLING_RATE |
Exception sampling rate (0.0-1.0) | 1.0 |
AIVORY_MAX_DEPTH |
Variable capture depth | 3 |
AIVORY_DEV_MODE |
Enable debug logging | false |
var config = new AgentConfig
{
ApiKey = "your-api-key",
BackendUrl = "wss://api.aivory.net",
Environment = "production",
SamplingRate = 1.0,
MaxDepth = 3,
DevMode = false
};
AIVoryMonitorAgent.Init(config, logger);Register the agent in your DI container:
builder.Services.AddSingleton(sp =>
{
var config = AgentConfig.FromEnvironment();
var logger = sp.GetRequiredService<ILogger<AIVoryMonitorAgent>>();
AIVoryMonitorAgent.Init(config, logger);
return AIVoryMonitorAgent.Instance;
});Add the middleware early in the pipeline to capture all exceptions:
app.UseAIVoryMonitor(); // Add this early
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();Capture exceptions in controllers:
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> CreateOrder(Order order)
{
try
{
var result = await _orderService.CreateAsync(order);
return Ok(result);
}
catch (Exception ex)
{
var context = new Dictionary<string, object>
{
{ "orderId", order.Id },
{ "userId", User.Identity?.Name }
};
ex.CaptureWithAIVory(context);
throw;
}
}
}Clone the repository and build:
git clone https://github.com/aivory/aivory-monitor.git
cd aivory-monitor/monitor-agents/agent-dotnet
dotnet restore
dotnet build
dotnet testCreate NuGet package:
dotnet pack -c ReleaseThe agent uses multiple mechanisms to capture exceptions:
- AppDomain.UnhandledException: Captures unhandled exceptions on any thread
- Manual Capture: Explicit
CaptureException()calls in try-catch blocks - Middleware: Automatic capture of ASP.NET Core request exceptions
For each exception, the agent captures:
- Full stack trace with line numbers
- Local variables at each stack frame (up to configured depth)
- Exception type and message
- Request context (HTTP method, path, headers, user)
- Environment metadata (hostname, runtime version, timestamp)
- Custom context provided by application code
- WebSocket connection to AIVory backend
- Automatic reconnection on connection loss
- Message queuing during disconnection
- Graceful shutdown on process exit
- Minimal overhead when no exceptions occur
- Asynchronous exception processing
- Configurable sampling to reduce load
- Automatic throttling under high exception rates
Check that AIVORY_API_KEY is set and valid:
echo $AIVORY_API_KEY # Linux/macOS
echo %AIVORY_API_KEY% # WindowsEnable debug logging:
var config = AgentConfig.FromEnvironment();
config.DevMode = true;
AIVoryMonitorAgent.Init(config, logger);Verify the agent is initialized before exceptions occur:
// Initialize in Program.cs or Startup.cs
AIVoryMonitorAgent.Init(config, logger);
// Then start application
app.Run();Reduce variable capture depth:
export AIVORY_MAX_DEPTH=1Enable sampling to capture only a percentage of exceptions:
export AIVORY_SAMPLING_RATE=0.1 # Capture 10%Check firewall rules allow WebSocket connections:
# Test connectivity
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
https://api.aivory.net/ws/monitor/agentUse HTTP backend URL for environments that block WebSockets:
export AIVORY_BACKEND_URL=https://api.aivory.netThe agent can coexist with other monitoring tools:
try
{
// Your code
}
catch (Exception ex)
{
// Capture in AIVory
ex.CaptureWithAIVory(context);
// Also send to other tools
_telemetryClient.TrackException(ex);
throw;
}Copyright (c) AIVory. All rights reserved.