Skip to content

Instantly share code, notes, and snippets.

@mniak
Last active July 11, 2018 14:12
Show Gist options
  • Save mniak/fafaeab76a3bdceac55cd874532bc093 to your computer and use it in GitHub Desktop.
Save mniak/fafaeab76a3bdceac55cd874532bc093 to your computer and use it in GitHub Desktop.
Custom #sentry target for #nlog
public class CustomSentryTarget : Target
{
protected override void Write(LogEventInfo logEvent)
{
if (logEvent.Exception != null)
{
SentryEvent sentryEvent = CreateSentryEvent(logEvent);
SentryHelper.RavenClient.Capture(sentryEvent);
}
else
{
var breadcrumb = CreateSentryBreadcrumb(logEvent);
SentryHelper.RavenClient.AddTrail(breadcrumb);
}
}
private SentryEvent CreateSentryEvent(LogEventInfo logEvent)
{
var level = ConvertToErrorLevel(logEvent.Level);
var se = new SentryEvent(logEvent.Exception);
se.Message = logEvent.FormattedMessage;
se.Level = level;
if (TryParseClassNamespace(logEvent.LoggerName, out string @class, out string @namespace))
{
se.Tags["class"] = @class;
se.Tags["namespace"] = @namespace;
}
else
{
se.Tags["nlog_logger"] = logEvent.LoggerName;
}
var extra = new Dictionary<string, string>();
FillDictionary(extra, logEvent);
se.Extra = extra;
return se;
}
private bool TryParseClassNamespace(string typename, out string @class, out string @namespace)
{
@class = null;
@namespace = null;
if (string.IsNullOrWhiteSpace(typename))
return false;
try
{
var t = Type.GetType(typename);
@class = t.Name;
@namespace = t.Namespace;
return true;
}
catch { return false; }
}
private Breadcrumb CreateSentryBreadcrumb(LogEventInfo logEvent)
{
var level = ConvertToBreadcrumbLevel(logEvent.Level);
var bc = new Breadcrumb(logEvent.LoggerName);
bc.Level = level;
bc.Message = logEvent.FormattedMessage;
bc.Data = new Dictionary<string, string>();
FillDictionary(bc.Data, logEvent);
return bc;
}
private static void FillDictionary(IDictionary<string, string> dictionary, LogEventInfo logEvent)
{
//if (logEvent.SequenceID != default(int))
// dictionary["seq"] = logEvent.SequenceID.ToString();
if (logEvent.CallerClassName != null)
dictionary["caller_class"] = logEvent.CallerClassName;
if (logEvent.CallerFilePath != null)
dictionary["caller_file"] = logEvent.CallerFilePath;
if (logEvent.CallerLineNumber != default(int))
dictionary["caller_line"] = logEvent.CallerLineNumber.ToString();
if (logEvent.CallerMemberName != null)
dictionary["caller_member"] = logEvent.CallerMemberName;
if (logEvent.Properties != null)
{
foreach (var kv in logEvent.Properties)
{
dictionary[kv.Key.ToString()] = kv.Value.ToString();
}
}
}
private BreadcrumbLevel ConvertToBreadcrumbLevel(LogLevel level)
{
if (level == LogLevel.Info) return BreadcrumbLevel.Info;
if (level == LogLevel.Warn) return BreadcrumbLevel.Warning;
if (level == LogLevel.Error) return BreadcrumbLevel.Error;
if (level == LogLevel.Fatal) return BreadcrumbLevel.Critical;
return BreadcrumbLevel.Debug;
}
private ErrorLevel ConvertToErrorLevel(LogLevel level)
{
if (level == LogLevel.Info) return ErrorLevel.Info;
if (level == LogLevel.Warn) return ErrorLevel.Warning;
if (level == LogLevel.Error) return ErrorLevel.Error;
if (level == LogLevel.Fatal) return ErrorLevel.Fatal;
return ErrorLevel.Debug;
}
}
public class SentryExceptionFilterAttribute : IExceptionFilter
{
public bool AllowMultiple => false;
public void OnException(ExceptionContext filterContext)
{
var ex = filterContext.Exception;
SentryHelper.RavenClient.Capture(new SentryEvent(ex));
}
}
public class SentryHelper
{
public static RavenClient RavenClient { get; }
static SentryHelper()
{
Environment = ConfigurationManager.AppSettings["Sentry:Environment"] ?? "NotSet";
Dsn = ConfigurationManager.AppSettings["Sentry:Dsn"] ?? "https://[email protected]/00000000";
RavenClient = new RavenClient(Dsn)
{
Environment = Environment,
Logger = "backend"
};
}
public static string Environment { get; }
public static string Dsn { get; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment