Skip to content

Commit

Permalink
Merge pull request #145 from getsentry/feature/serilog-breadcrumbs
Browse files Browse the repository at this point in the history
feat(serilog): Breadcrumbs and Events
  • Loading branch information
bruno-garcia authored Dec 3, 2018
2 parents 2964555 + 35c21ad commit 94b6a4e
Show file tree
Hide file tree
Showing 14 changed files with 467 additions and 130 deletions.
7 changes: 7 additions & 0 deletions Sentry.sln
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sentry.Serilog.Tests", "tes
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sentry.Samples.Serilog", "samples\Sentry.Samples.Serilog\Sentry.Samples.Serilog.csproj", "{B7EDB922-4024-4546-B6E4-E5AB9016369F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sentry.Samples.AspNetCore.Serilog", "samples\Sentry.Samples.AspNetCore.Serilog\Sentry.Samples.AspNetCore.Serilog.csproj", "{1930A5D5-356B-43F9-AEDF-CB76254C5933}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -165,6 +167,10 @@ Global
{B7EDB922-4024-4546-B6E4-E5AB9016369F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7EDB922-4024-4546-B6E4-E5AB9016369F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7EDB922-4024-4546-B6E4-E5AB9016369F}.Release|Any CPU.Build.0 = Release|Any CPU
{1930A5D5-356B-43F9-AEDF-CB76254C5933}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1930A5D5-356B-43F9-AEDF-CB76254C5933}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1930A5D5-356B-43F9-AEDF-CB76254C5933}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1930A5D5-356B-43F9-AEDF-CB76254C5933}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -190,6 +196,7 @@ Global
{2CF1FBEF-93C4-404E-94F6-543D08842633} = {AF6AF4C7-8AA2-4D59-8064-2D79560904EB}
{EBABB411-4481-478B-BEAD-009D1EE6D259} = {83263231-1A2A-4733-B759-EEFF14E8C5D5}
{B7EDB922-4024-4546-B6E4-E5AB9016369F} = {77454495-55EE-4B40-A089-71B9E8F82E89}
{1930A5D5-356B-43F9-AEDF-CB76254C5933} = {77454495-55EE-4B40-A089-71B9E8F82E89}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0C652B1A-DF72-4EE5-A98B-194FE2C054F6}
Expand Down
83 changes: 83 additions & 0 deletions samples/Sentry.Samples.AspNetCore.Serilog/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Sentry.Serilog;
using Serilog;
using Serilog.Events;

namespace Sentry.Samples.AspNetCore.Serilog
{
public class Program
{
public static void Main(string[] args) => BuildWebHost(args).Run();

public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)

.UseSerilog((h, c) =>
c.Enrich.FromLogContext()
.MinimumLevel.Debug()
.WriteTo.Console()
// Add Sentry integration with Serilog
// Two levels are used to configure it.
// One sets which log level is minimally required to keep a log message as breadcrumbs
// The other sets the minimum level for messages to be sent out as events to Sentry
.WriteTo.Sentry(s =>
{
s.MinimumBreadcrumbLevel = LogEventLevel.Debug;
s.MinimumEventLevel = LogEventLevel.Error;
}))

// Add Sentry integration
// It can also be defined via configuration (including appsettings.json)
// or coded explicitly, via parameter like:
// .UseSentry("dsn") or .UseSentry(o => o.Dsn = ""; o.Release = "1.0"; ...)
.UseSentry()

// The App:
.Configure(a =>
{
// An example ASP.NET Core middleware that throws an
// exception when serving a request to path: /throw
a.Use(async (context, next) =>
{
// See MinimumBreadcrumbLevel set at the Serilog configuration above
Log.Logger.Debug("Static Serilog logger debug log stored as breadcrumbs.");

var log = context.RequestServices.GetService<ILoggerFactory>()
.CreateLogger<Program>();

log.LogInformation("Handling some request...");

// Sends an event which includes the info and debug messages above
Log.Logger.Error("Logging using static Serilog directly also goes to Sentry.");

if (context.Request.Path == "/throw")
{
var hub = context.RequestServices.GetService<IHub>();
hub.ConfigureScope(s =>
{
// More data can be added to the scope like this:
s.SetTag("Sample", "ASP.NET Core"); // indexed by Sentry
s.SetExtra("Extra!", "Some extra information");
});

// Logging through the ASP.NET Core `ILogger` while using Serilog
log.LogInformation("Logging info...");
log.LogWarning("Logging some warning!");

// The following exception will be captured by the SDK and the event
// will include the Log messages and any custom scope modifications
// as exemplified above.
throw new Exception("An exception thrown from the ASP.NET Core pipeline");
}

await next();
});
})
.Build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59539/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "throw",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Sentry.Samples.AspNetCore.Basic": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "throw",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:59540/"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.2" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Sentry.AspNetCore\Sentry.AspNetCore.csproj" />
<ProjectReference Include="..\..\src\Sentry.Serilog\Sentry.Serilog.csproj" />
</ItemGroup>

</Project>
21 changes: 21 additions & 0 deletions samples/Sentry.Samples.AspNetCore.Serilog/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
// Example configuration via JSON. Only a subset of the settings below:
// All Sentry settings can also be configured via code or environment variables:
"Sentry": {
// The DSN can also be set via environment variable
"Dsn": "https://5fd7a6cda8444965bade9ccfd3df9882@sentry.io/1188141",
// Opt-in for payload submission
"IncludeRequestPayload": true,
// Sends Cookies, User Id when one is logged on and user IP address to sentry. It's turned off by default.
"SendDefaultPii": true,
// Whether to add System.Diagnostics.Activity data to the event::
// For more: https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/ActivityUserGuide.md
"IncludeActivityData": true,
// Send the stack trace of captured messages (e.g: a LogWarning without an exception)
"AttachStackTrace": true,
// The flag below can be used to see the internal logs of the SDK in the applications log (it's off by default)
"Debug": true,
// By default the level is Debug but it can be changed to any level of SentryLevel enum
"DiagnosticsLevel": "Error"
}
}
29 changes: 24 additions & 5 deletions samples/Sentry.Samples.Serilog/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Sentry;
using Sentry.Serilog;
using Serilog;
using Serilog.Context;
Expand All @@ -12,7 +13,17 @@ private static void Main()
.Enrich.FromLogContext()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.Sentry("https://5fd7a6cda8444965bade9ccfd3df9882@sentry.io/1188141", restrictedToMinimumLevel: LogEventLevel.Information)
// Other overloads exist, for example, configure the SDK with only the DSN or no parameters at all.
.WriteTo.Sentry(o =>
{
o.MinimumBreadcrumbLevel = LogEventLevel.Debug; // Debug and higher are stored as breadcrumbs (default os Information)
o.MinimumEventLevel = LogEventLevel.Error; // Error and higher is sent as event (default is Error)
// If DSN is not set, the SDK will look for an environment variable called SENTRY_DSN. If nothing is found, SDK is disabled.
o.Dsn = new Dsn("https://5fd7a6cda8444965bade9ccfd3df9882@sentry.io/1188141");
o.AttachStacktrace = true;
o.SendDefaultPii = true; // send PII like the username of the user logged in to the device
// Other configuration
})
.CreateLogger();

try
Expand All @@ -25,9 +36,16 @@ private static void Main()
CheeseWheels = 512
}))
{
// Logger config enables the Sink only for level INFO or higher so the Debug
// Does not result in an event in Sentry
Log.Debug("Debug message which is not sent.");
// Minimum Breadcrumb and Event log levels are set to levels higher than Verbose
// In this case, Verbose messages are ignored
Log.Verbose("Verbose message which is not sent.");

// Minimum Breadcrumb level is set to Debug so the following message is stored in memory
// and sent with following events of the same Scope
Log.Debug("Debug message stored as breadcrumb.");

// Sends an event and stores the message as a breadcrumb too, to be sent with any upcoming events.
Log.Error("Some event that includes the previous breadcrumbs");

try
{
Expand All @@ -36,7 +54,8 @@ private static void Main()
catch (Exception e)
{
e.Data.Add("details", "Do work always throws.");
Log.Error(e, "Error: with exception");
Log.Fatal(e, "Error: with exception");
throw;
}
}
}
Expand Down
27 changes: 0 additions & 27 deletions src/Sentry.Serilog/LevelMapping.cs

This file was deleted.

47 changes: 47 additions & 0 deletions src/Sentry.Serilog/LogLevelExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Sentry.Protocol;
using Serilog.Events;

namespace Sentry.Serilog
{
internal static class LogLevelExtensions
{
public static SentryLevel? ToSentryLevel(this LogEventLevel loggingLevel)
{
switch (loggingLevel)
{
case LogEventLevel.Fatal:
return SentryLevel.Fatal;
case LogEventLevel.Error:
return SentryLevel.Error;
case LogEventLevel.Warning:
return SentryLevel.Warning;
case LogEventLevel.Information:
return SentryLevel.Info;
case LogEventLevel.Debug:
return SentryLevel.Debug;
}

return null;
}

public static BreadcrumbLevel ToBreadcrumbLevel(this LogEventLevel level)
{
switch (level)
{
case LogEventLevel.Verbose:
case LogEventLevel.Debug:
return BreadcrumbLevel.Debug;
case LogEventLevel.Information:
return BreadcrumbLevel.Info;
case LogEventLevel.Warning:
return BreadcrumbLevel.Warning;
case LogEventLevel.Error:
return BreadcrumbLevel.Error;
case LogEventLevel.Fatal:
return BreadcrumbLevel.Critical;
default:
return (BreadcrumbLevel)level;
}
}
}
}
43 changes: 43 additions & 0 deletions src/Sentry.Serilog/SentrySerilogOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using Sentry.Protocol;
using Serilog.Events;

namespace Sentry.Serilog
{
/// <summary>
/// Sentry Options for Serilog logging
/// </summary>
/// <inheritdoc />
public class SentrySerilogOptions : SentryOptions
{
/// <summary>
/// Whether to initialize this SDK through this integration
/// </summary>
public bool InitializeSdk { get; set; } = true;

/// <summary>
/// Minimum log level to send an event.
/// </summary>
/// <remarks>
/// Events with this level or higher will be sent to Sentry.
/// </remarks>
/// <value>
/// The minimum event level.
/// </value>
public LogEventLevel MinimumEventLevel { get; set; }

/// <summary>
/// Minimum log level to record a breadcrumb.
/// </summary>
/// <remarks>Events with this level or higher will be stored as <see cref="Breadcrumb"/></remarks>
/// <value>
/// The minimum breadcrumb level.
/// </value>
public LogEventLevel MinimumBreadcrumbLevel { get; set; }

/// <summary>
/// Optional <see cref="IFormatProvider"/>
/// </summary>
public IFormatProvider FormatProvider { get; set; }
}
}
Loading

0 comments on commit 94b6a4e

Please # to comment.