Airbrake Notifier for .NET
Airbrake is an online tool that provides robust error tracking in most of your C#/.NET applications. In doing so, it allows you to easily review errors, tie an error to an individual piece of code, and trace the cause back to recent changes. The Airbrake dashboard provides easy categorization, searching, and prioritization of errors so that when they occur, your team can quickly determine the root cause.
Sharpbrake is a C# notifier library for Airbrake. It provides minimalist API to send C# exceptions and error messages to the Airbrake dashboard. The library perfectly suits any type of C# applications.
The library comes with the following integrations:
For .NET 4.5.2 applications and above install the Sharpbrake.Client
package
available on NuGet via your
Package Manager Console:
PM> Install-Package Sharpbrake.Client
This is the minimal example that you can use to test Sharpbrake with your project.
using System;
using Sharpbrake.Client;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var airbrake = new AirbrakeNotifier(new AirbrakeConfig
{
ProjectId = "113743",
ProjectKey = "81bbff95d52f8856c770bb39e827f3f6"
});
try
{
throw new Exception("Oops!");
}
catch (Exception ex)
{
var notice = airbrake.BuildNotice(ex);
var response = airbrake.NotifyAsync(notice).Result;
Console.WriteLine("Status: {0}, Id: {1}, Url: {2}", response.Status, response.Id, response.Url);
}
}
}
}
Consult our documentation to learn how to create an Airbrake-enabled console app.
Before using the library and its notifiers, you must configure them. In most cases, it is sufficient to configure only one, default, notifier.
var airbrake = new AirbrakeNotifier(new AirbrakeConfig
{
ProjectId = "113743",
ProjectKey = "81bbff95d52f8856c770bb39e827f3f6"
});
You must set both ProjectId
& ProjectKey
.
To find your ProjectId
and ProjectKey
navigate to your project's General
Settings and copy the values from the right sidebar.
There are multiple ways to set these values:
Setting explicitly:
var config = new AirbrakeConfig {
ProjectId = "113743",
ProjectKey = "81bbff95d52f8856c770bb39e827f3f6"
};
Using App.config
or Web.config
:
<appSettings>
<add key="Airbrake.ProjectId" value="113743" />
<add key="Airbrake.ProjectKey" value="81bbff95d52f8856c770bb39e827f3f6" />
</appSettings>
var settings = ConfigurationManager.AppSettings.AllKeys
.Where(key => key.StartsWith("Airbrake", StringComparison.OrdinalIgnoreCase))
.ToDictionary(key => key, key => ConfigurationManager.AppSettings[key]);
var airbrakeConfiguration = AirbrakeConfig.Load(settings);
Using airbrake.json
. Use comma-separated values to add more than one
argument for options that support it:
{
"Airbrake": {
"ProjectId": "113743",
"ProjectKey": "81bbff95d52f8856c770bb39e827f3f6"
}
}
var path = "airbrake.json";
var configurationBuilder = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile(path)
.Build();
var settings = configurationBuilder.AsEnumerable()
.Where(setting => setting.Key.StartsWith("Airbrake"))
.ToDictionary(setting => setting.Key, setting => setting.Value);
var airbrakeConfiguration = AirbrakeConfig.Load(settings);
The library can log responses from Airbrake via the LogFile
option. The option
accepts a path to the log file. Supports relative (to your app's executable) and
absolute paths. By default, it's not set.
var config = new AirbrakeConfig {
LogFile = "airbrake.log"
};
Configures the environment the application is running in. Helps the Airbrake dashboard to distinguish between errors occurring in different environments. By default, it's not set.
var config = new AirbrakeConfig {
Environment = "production"
};
The version of your application that you can pass to differentiate errors between multiple versions. It's not set by default.
var config = new AirbrakeConfig {
AppVersion = "1.0.1"
};
By default, it is set to api.airbrake.io
. A host
is a web address containing a
scheme ("http" or "https"), a host and a port. You can omit the port (80 will be
assumed) and the scheme ("https" will be assumed).
var config = new AirbrakeConfig {
Host = "http://127.0.0.1:8000"
};
If your server is not able to directly reach Airbrake, you can use a built-in proxy. By default, Sharpbrake uses a direct connection.
var config = new AirbrakeConfig {
ProxyUri = "http://46.166.165.63:8080",
ProxyUsername = "username",
ProxyPassword = "s3kr3t"
};
Setting this option allows Airbrake to filter errors occurring in unwanted
environments such as test
. By default, it is not set, which means Sharpbrake
sends errors occurring in all environments.
var config = new AirbrakeConfig {
IgnoreEnvironments = new List<string> { "development" }
};
Specifies which keys in the payload (parameters, session data, environment data,
etc.) should be filtered. Before sending an error, filtered keys will be
substituted with the [Filtered]
label.
var config = new AirbrakeConfig {
Blocklist = new List<string> { "password", "creditCard", "email" }
};
// The dashboard will display this parameter as filtered, but other values won't
// be affected:
// { user: 'John',
// password: '[Filtered]',
// email: '[Filtered]',
// creditCard: '[Filtered]' }
Note: Blocklist
has higher priority than Allowlist
. It means
that if you set the same value into both blacklist and whitelist - that value
will be filtered out.
Specifies which keys in the payload (parameters, session data, environment data,
etc.) should not be filtered. All other keys will be substituted with the
[Filtered]
label.
var config = new AirbrakeConfig {
Allowlist = new List<string> { "user", "email", "accountId" }
};
// The dashboard will display this parameter as is, but all other values will be
// filtered:
// { user: 'John',
// password: '[Filtered]',
// email: '[email protected]',
// accountId: 42 }
Specifies formatting information for error messages. Check IFormatProvider for details.
AirbrakeConfig.Load
accepts a Dictionary
consisting of config option names
and their values.
// Construct a dictionary with configuration options
var settings = ConfigurationManager.AppSettings.AllKeys
.Where(key => key.StartsWith("Airbrake", StringComparison.OrdinalIgnoreCase))
.ToDictionary(key => key, key => ConfigurationManager.AppSettings[key]);
// Create a config from that dictionary
var config = AirbrakeConfig.Load(settings);
BuildNotice
builds a notice with error details that can be sent to the
Airbrake dashboard with the help of NotifyAsync
:
notifier.BuildNotice(Severity.Error, exception, "Failed with message {0}", exception.Message);
NotifyAsync
asynchronously sends a notice with error details to the Airbrake
dashboard. It also provides control over the response object from Airbrake.
In .NET 4.5 and above you can use task-based programming model. Example of using
a continuation, which prints URL to the error in the Airbrake dashboard:
airbrake.NotifyAsync(notice)
.ContinueWith(response => Console.WriteLine(response.Result.Url));
The method also supports async/await
:
var response = await airbrake.NotifyAsync(notice);
Console.WriteLine(response.Url);
SetHttpContext
attaches HTTP context properties to the notice:
var notice = notifier.BuildNotice(ex);
notifier.SetHttpContext(notice, new AspNetCoreHttpContext(context));
notifier.NotifyAsync(notice);
Usually, our integrations perform this for you.
AddFilter
A notice can be customized or ignored before it is sent to Airbrake via
AddFilter
. A lambda expression that is passed to the AddFilter
method
accepts Notice
that can be processed by your code. The Notice
object is
pre-populated with errors, context and params, so you can freely modify these
values if you wish. The Notice
object is not sent to Airbrake if the lambda
expression returns null
:
airbrake.AddFilter(notice =>
{
// ignore notice if email is "[email protected]"
if (notice.Context.User?.Email == "[email protected]")
return null;
// clear environment variables with "token"-related keys
if (notice.EnvironmentVars != null)
{
new List<string>(notice.EnvironmentVars.Keys).ForEach(key =>
{
if (key.ToLowerInvariant().Contains("token"))
notice.EnvironmentVars[key] = string.Empty;
});
}
return notice;
});
Exception
and HttpContext
are properties that can be used to retrieve the
values that the Notice
object was built from.
Used to access additional exception properties. For example, if your exception is
an HttpException
, you can ignore it if GetHTTPCode()
returns 404:
airbrake.AddFilter(notice =>
{
var exception = notice.Exception as HttpException;
if (exception != null && exception.GetHttpCode() == 404)
return null;
return notice;
});
Used to retrieve HTTP context properties:
airbrake.AddFilter(notice =>
{
notice.Params["response"] = notice.HttpContext.Response
return notice;
});
Note: Notice that exceeds 64 KB is truncated before sending.
Severity allows categorizing how severe an error is. By
default, it's set to error
. To redefine severity, simply pass the Severity
as a parameter to the BuildNotice
method. For example:
airbrake.BuildNotice(Severity.Critical, exception);
Install the Sharpbrake.Http.Module
package from NuGet (you can use "Package
Manager Console" from Visual Studio):
PM> Install-Package Sharpbrake.Http.Module
Configure appSettings
in Web.config
(how to configure):
<appSettings>
<add key="Airbrake.ProjectId" value="113743"/>
<add key="Airbrake.ProjectKey" value="81bbff95d52f8856c770bb39e827f3f6"/>
</appSettings>
Add the AirbrakeHttpModule
module to your system.webServer
in
Web.config
:
<system.webServer>
<modules>
<add name="Airbrake" type="Sharpbrake.Http.Module.AirbrakeHttpModule, Sharpbrake.Http.Module"/>
</modules>
</system.webServer>
Install the Sharpbrake.Http.Middleware
package from NuGet (you can use
"Package Manager Console" from Visual Studio):
PM> Install-Package Sharpbrake.Http.Middleware
Configure appsettings.json
:
"Airbrake": {
"ProjectId": "113743",
"ProjectKey": "81bbff95d52f8856c770bb39e827f3f6",
}
Add the middleware to your Startup.cs
:
using Sharpbrake.Http.Middleware;
Then make sure to add AirbrakeMiddleware
to your pipeline by updating the
Configure
method:
app.UseAirbrake(Configuration.GetSection("Airbrake"));
Note: In most cases you want to put AirbrakeMiddleware
as a topmost
middleware component to load it as early as possible. However, if you use
app.UseDeveloperExceptionPage
and/or app.UseExceptionHandler
, then
AirbrakeMiddleware
must be put after these components.
You can use the IAirbrakeFeature
feature from the Features
collection of
HttpContext
to access the notifier that was initialized by the middleware:
var airbrake = HttpContext.Features.Get<IAirbrakeFeature>().GetNotifier();
Airbrake NLog target is used to pass an error and exception from log message to the Airbrake dashboard.
Install the Sharpbrake.NLog
package from NuGet (you can use "Package
Manager Console" from Visual Studio):
PM> Install-Package Sharpbrake.NLog
Register the Sharpbrake.NLog
assembly in the <extensions />
section
of the nlog.config file:
<extensions>
<add assembly="Sharpbrake.NLog"/>
</extensions>
Define the Airbrake target in the <targets />
section and appropriate
routing rules in the <rules />
section of nlog.config
:
<targets>
<target name="airbrake"
type="Airbrake"
projectId="113743"
projectKey="81bbff95d52f8856c770bb39e827f3f6"
environment="live"
ignoreEnvironments="dev"
/>
<!-- other targets -->
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="airbrake" />
<!-- other rules -->
</rules>
Note that both projectId
and projectKey
are required parameters. You can
set any configuration option supported by the Airbrake client in the declarative
way (how to configure).
When you need to access Notifier
programmatically (e.g. for setting up filters
in your code) you can get it from the AirbrakeTarget
object:
var airbrakeTarget = (AirbrakeTarget)LogManager.Configuration.AllTargets
.FirstOrDefault(t => t.GetType() == typeof(AirbrakeTarget));
airbrakeTarget?.Notifier.AddFilter(notice =>
{
// clear environment variables with "token"-related keys
new List<string>(notice.EnvironmentVars.Keys).ForEach(key =>
{
if (key.ToLowerInvariant().Contains("token"))
notice.EnvironmentVars[key] = "[removed]";
});
return notice;
});
With Airbrake NLog target for ASP.NET you get, in addition, reporting of HTTP context properties in web applications.
Install the Sharpbrake.NLog.Web
package from NuGet (you can use "Package
Manager Console" from Visual Studio):
PM> Install-Package Sharpbrake.NLog.Web
Register the Sharpbrake.NLog.Web
assembly in the <extensions />
section
of the nlog.config file:
<extensions>
<add assembly="Sharpbrake.NLog.Web"/>
</extensions>
Define the Airbrake target in the <targets />
section and appropriate
routing rules in the <rules />
section of nlog.config
. All supported
settings are the same as for the regular Airbrake target.
<targets>
<target name="airbrake"
type="Airbrake"
projectId="113743"
projectKey="81bbff95d52f8856c770bb39e827f3f6"
environment="live"
ignoreEnvironments="dev"
/>
<!-- other targets -->
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="airbrake" />
<!-- other rules -->
</rules>
For ASP.NET Core you need to call the following code in the Configure
method
in Startup.cs
:
app.ConfigureAirbrakeTarget();
The Notifier
object can be accessed from here for the additional configuration:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// add NLog to ASP.NET Core
loggerFactory.AddNLog();
// add NLog.Web
app.AddNLogWeb();
// configure the Airbrake target with HTTP context accessor
app.ConfigureAirbrakeTarget();
// example of getting access to the Notifier instance
var target = LogManager.Configuration.FindTargetByName<AirbrakeTarget>("airbrake");
target?.Notifier.AddFilter(notice =>
{
// clear environment variables with "token"-related keys
new List<string>(notice.EnvironmentVars.Keys).ForEach(key =>
{
if (key.ToLowerInvariant().Contains("token"))
notice.EnvironmentVars[key] = "[removed]";
});
return notice;
});
// remaining code...
}
Airbrake log4net appender sends an exception or/and error from the logging event to the Airbrake dashboard.
Install the Sharpbrake.Log4net
package from NuGet (you can use "Package
Manager Console" from Visual Studio):
PM> Install-Package Sharpbrake.Log4net
Define the Sharpbrake.Log4net.AirbrakeAppender
appender in the
log4net configuration file:
<appender name="Airbrake" type="Sharpbrake.Log4net.AirbrakeAppender, Sharpbrake.Log4net">
<projectId value="113743" />
<projectKey value="81bbff95d52f8856c770bb39e827f3f6" />
</appender>
Add Airbrake appender to the root logger:
<root>
<level value="DEBUG" />
<appender-ref ref="Airbrake" />
<!-- other appenders... -->
</root>
Note that both projectId
and projectKey
are required parameters. You can
set any configuration option supported by the Airbrake client in the declarative
way within <appender />
section (how to configure).
With Airbrake log4net appender for ASP.NET you get, in addition, reporting of HTTP context properties in web applications.
Install the Sharpbrake.Log4net.Web
package from NuGet (you can use "Package
Manager Console" from Visual Studio):
PM> Install-Package Sharpbrake.Log4net.Web
Define the Sharpbrake.Log4net.Web.AirbrakeAppender
appender in the
log4net configuration file:
<appender name="Airbrake" type="Sharpbrake.Log4net.Web.AirbrakeAppender, Sharpbrake.Log4net.Web">
<projectId value="113743" />
<projectKey value="81bbff95d52f8856c770bb39e827f3f6" />
</appender>
Note that you need to use Sharpbrake.Log4net.Web.AirbrakeAppender
from Sharpbrake.Log4net.Web
assembly and not plain Sharpbrake.Log4net.AirbrakeAppender
(without Web
part) to get support
for reporting HTTP context properties.
Add Airbrake appender to the root logger:
<root>
<level value="DEBUG" />
<appender-ref ref="Airbrake" />
<!-- other appenders... -->
</root>
For ASP.NET Core apps you need to set ContextAccessor
property in appender so it can
access HttpContext
. You can do that directly or by calling the helper method from the
AspNetCoreExtensions
class:
4.1. In Startup.cs
add using Sharpbrake.Log4net.Web
to get access to the
AspNetCoreExtensions
class.
4.2. In the Configure
method (Startup.cs
file) call the ConfigureAirbrakeAppender
method after setting up log4net functionality:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var repoAssembly = Assembly.GetEntryAssembly();
var loggerRepository = log4net.LogManager.CreateRepository(repoAssembly,
typeof(log4net.Repository.Hierarchy.Hierarchy));
log4net.Config.XmlConfigurator.Configure(loggerRepository,
new FileInfo("log4net.config"));
app.ConfigureAirbrakeAppender(repoAssembly);
// remaining code...
}
Provider notifies the Airbrake dashboard of an error with the help of Microsoft.Extensions.Logging methods.
Install the Sharpbrake.Extensions.Logging
package from NuGet (you can use "Package
Manager Console" from Visual Studio):
PM> Install-Package Sharpbrake.Extensions.Logging
Configure the Airbrake logging provider:
2.1. In your Startup.cs
add the import:
using Sharpbrake.Extensions.Logging
2.2. Add the Airbrake provider to the list of loggers:
ConfigureServices
method:public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// adds the Airbrake provider with HTTP Context accessor
// to the list of services
var contextAccessor = new HttpContextAccessor();
services.AddSingleton<IHttpContextAccessor>(contextAccessor);
services.AddLogging(logging =>
{
logging.AddAirbrake(Configuration.GetSection("Airbrake"), contextAccessor);
});
}
Configure
method:loggerFactory.AddAirbrake(Configuration.GetSection("Airbrake"),
app.ApplicationServices.GetService<IHttpContextAccessor>());
The code above assumes that the configuration options are defined in the registered configuration
file (e.g. appsettings.json
). Example of such configuration file:
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
},
"Airbrake": {
"ProjectId": "113743",
"ProjectKey": "81bbff95d52f8856c770bb39e827f3f6"
}
}
To get access to the HTTP content app.ApplicationServices.GetService<IHttpContextAccessor>()
is used.
Minimum log level can be set here to filter errors with lower severities
(defaults to LogLevel.Error
):
loggerFactory.AddAirbrake(Configuration.GetSection("Airbrake"),
app.ApplicationServices.GetService<IHttpContextAccessor>(),
LogLevel.Warning);
More advanced setup can be used to better suit your needs. Here is an example of how to define a notifier with additional filtering rules:
var settings = Configuration.GetSection("Airbrake")
.GetChildren()
.ToDictionary(setting => setting.Key, setting => setting.Value);
var airbrakeNotifier = new AirbrakeNotifier(AirbrakeConfig.Load(settings));
// clear environment variables with "token"-related keys
airbrakeNotifier.AddFilter(notice =>
{
if (notice?.EnvironmentVars != null)
{
new List<string>(notice.EnvironmentVars.Keys).ForEach(key =>
{
if (key.ToLowerInvariant().Contains("token"))
notice.EnvironmentVars[key] = "[removed]";
});
}
return notice;
});
loggerFactory.AddAirbrake(airbrakeNotifier,
app.ApplicationServices.GetService<IHttpContextAccessor>());
If something goes wrong with the notifier itself (a notice is not being sent, some internal exception happens, etc.) you may want to turn on the tracing mode and get more insights on what is going on.
Tracing to the Debug window can be enabled with the following code:
Sharpbrake.Client.InternalLogger.Enable(msg => Debug.WriteLine(msg));
You can output to the file as well:
var traceWriter = System.IO.TextWriter.Synchronized(
System.IO.File.AppendText("AirbrakeNotifier.log"));
Sharpbrake.Client.InternalLogger.Enable(msg =>
{
traceWriter.WriteLine(msg);
traceWriter.Flush();
});
Tracing can be disabled (this is the default state) with the code:
Sharpbrake.Client.InternalLogger.Disable();
Please refer to Sharpbrake for .NET 3.5 if your app uses .NET Framework before 4.5.2.
The project uses the MIT License. See LICENSE.md for details.