Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,4 @@ paket-files/
.idea/
*.sln.iml
src/Seq.Extensions.Logging/project.json.orig
*.orig
64 changes: 18 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Seq.Extensions.Logging [![Build status](https://ci.appveyor.com/api/projects/status/h7r1hv3cpd6e2ou3?svg=true)](https://ci.appveyor.com/project/datalust/seq-extensions-logging) [![NuGet Pre Release](https://img.shields.io/nuget/vpre/Seq.Extensions.Logging.svg)](https://nuget.org/packages/Seq.Extensions.Logging) [![Join the chat at https://gitter.im/datalust/seq](https://img.shields.io/gitter/room/datalust/seq.svg)](https://gitter.im/datalust/seq)

[Seq](https://getseq.net) is a flexible self-hosted back-end for the ASP.NET Core logging subsystem (_Microsoft.Extensions.Logging_). Log events generated by the framework and application code are sent over HTTP to a Seq server, where the structured data associated with each event is used for powerful filtering, correlation, and analysis.
[Seq](https://datalust.co/seq) is a flexible self-hosted back-end for the ASP.NET Core logging subsystem (_Microsoft.Extensions.Logging_). Log events generated by the framework and application code are sent over HTTP to a Seq server, where the structured data associated with each event is used for powerful filtering, correlation, and analysis.

For an example, see [the _dotnetconf_ deep dive session](https://channel9.msdn.com/Events/dotnetConf/2016/ASPNET-Core--deep-dive-on-building-a-real-website-with-todays-bits).

Expand All @@ -14,39 +14,22 @@ The instructions that follow are for **.NET Core 2.0+**.

Add [the NuGet package](https://nuget.org/packages/seq.extensions.logging) to your project either by editing the CSPROJ file, or using the NuGet package manager:

```powershell
Install-Package Seq.Extensions.Logging
```
dotnet add package Seq.Extensions.Logging
```

In `Program.cs`, call `AddSeq()` on the provided `ILoggingBuilder`.
In `Startup.cs`, call `AddSeq()` on the provided `ILoggingBuilder`.

```csharp
public static void Main(string[] args)
public class Startup
{
var webHost = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));

// Add this line
logging.AddSeq("http://localhost:5341");

logging.AddConsole();
logging.AddDebug();
})
.UseStartup<Startup>()
.Build();

webHost.Run();
public void ConfigureServices(IServiceCollection services)
{
// Added
services.AddLogging(builder => builder.AddSeq())

// Other configuration follows...
}
}
```

Expand Down Expand Up @@ -96,48 +79,37 @@ The `AddSeq()` method exposes some basic options for controlling the connection

| Parameter | Description | Example value |
| --------- | ----------- | ------------- |
| `apiKey` | A Seq [API key](http://docs.getseq.net/docs/api-keys) to authenticate or tag messages from the logger | `"1234567890"` |
| `apiKey` | A Seq [API key](http://docs.datalust.co/docs/api-keys) to authenticate or tag messages from the logger | `"1234567890"` |
| `levelOverrides` | A dictionary mapping logger name prefixes to minimum logging levels | `new Dictionary<string,LogLevel>{ ["Microsoft"] = LogLevel.Warning }` |
| `minimumLevel` | The level below which events will be suppressed (the default is `Information`) | `LogLevel.Trace` |

### JSON configuration

The logging level, Seq server URL, API key and other settings can be read from JSON configuration if desired.

In `appsettings.json` add a `"Seq"` property to `"Logging"` to configure levels for the Seq provider:
In `appsettings.json` add a `"Seq"` property to `"Logging"` to configure the server URL, API key, and levels for the Seq provider:

```json
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Information"
},
"Seq": {
"ServerUrl": "http://localhost:5341",
"ApiKey": "1234567890",
"LogLevel": {
"Default": "Trace",
"System": "Information",
"Microsoft": "Warning"
}
}
},
"Seq": {
"ServerUrl": "http://localhost:5341",
"ApiKey": "1234567890",
}
}
```

An additional root `"Seq"` property is used to configure the server URL and API key. To use this,
pass the configuration section to the `AddSeq()` method:

```csharp
logging.AddSeq(Configuration.GetSection("Seq"));
```

### Dynamic log level control

The logging provider will dynamically adjust the default logging level up or down based on the level associated with an API key in Seq. For further information see the [Seq documentation](http://docs.getseq.net/docs/using-serilog#dynamic-level-control).
The logging provider will dynamically adjust the default logging level up or down based on the level associated with an API key in Seq. For further information see the [Seq documentation](http://docs.datalust.co/docs/using-serilog#dynamic-level-control).

### Troubleshooting

Expand Down Expand Up @@ -173,7 +145,7 @@ Seq.Extensions.Logging.SelfLog.Enable(message => {

* Check the Seq _Ingestion Log_, as described in the _Server-side issues_ section above.
* Turn on the `SelfLog` as described above to check for connectivity problems and other issues on the client side.
* [Raise an issue](https://github.com/datalust/seq-extensions-logging/issues), ask for help on the [Seq support forum](http://docs.getseq.net/discuss) or email **support@getseq.net**.
* [Raise an issue](https://github.com/datalust/seq-extensions-logging/issues), ask for help on the [Seq support forum](http://docs.datalust.co/discuss) or email **support@datalust.co**.

### Migrating to Serilog

Expand Down
Binary file modified asset/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 2 additions & 5 deletions example/WebApplication/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,8 @@ public void ConfigureServices(IServiceCollection services)
{
services.AddLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
loggingBuilder.AddConfiguration(Configuration.GetSection("Logging"));

// Add a Seq logger.
loggingBuilder.AddSeq(Configuration.GetSection("Seq"));
// Add the Seq logger, with configuration from appsettings.json
loggingBuilder.AddSeq();

loggingBuilder.AddConsole();
loggingBuilder.AddDebug();
Expand Down
12 changes: 2 additions & 10 deletions example/WebApplication/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Information"
},
"Seq": {
"LogLevel": {
"Default": "Trace",
"System": "Information",
"Microsoft": "Warning"
}
"ServerUrl": "http://localhost:5341",
"ApiKey": ""
}
},
"Seq": {
"ServerUrl": "http://localhost:5341",
"ApiKey": ""
}
}
3 changes: 2 additions & 1 deletion seq-extensions-logging.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Serilog/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
using Serilog.Events;
using Serilog.Extensions.Logging;
using Serilog.Sinks.Seq;

#if LOGGING_BUILDER
using Microsoft.Extensions.DependencyInjection;
#endif
using Microsoft.Extensions.Logging.Configuration;

namespace Microsoft.Extensions.Logging
{
Expand Down Expand Up @@ -61,9 +59,6 @@ public static ILoggerFactory AddSeq(
return loggerFactory;
}


#if LOGGING_BUILDER

/// <summary>
/// Adds a Seq logger.
/// </summary>
Expand All @@ -79,9 +74,12 @@ public static ILoggingBuilder AddSeq(
if (loggingBuilder == null) throw new ArgumentNullException(nameof(loggingBuilder));
if (serverUrl == null) throw new ArgumentNullException(nameof(serverUrl));

var provider = CreateProvider(serverUrl, apiKey, LevelAlias.Minimum, null);

loggingBuilder.Services.AddSingleton<ILoggerProvider>(_ => provider);
loggingBuilder.Services.AddSingleton<ILoggerProvider>(s =>
{
var opts = s.GetService<ILoggerProviderConfiguration<SerilogLoggerProvider>>();
var provider = CreateProvider(opts?.Configuration, serverUrl, apiKey);
return provider;
});

return loggingBuilder;
}
Expand All @@ -105,8 +103,6 @@ public static ILoggingBuilder AddSeq(
return loggingBuilder;
}

#endif

static bool TryCreateProvider(
IConfigurationSection configuration,
LogLevel defaultMinimumLevel,
Expand Down Expand Up @@ -152,6 +148,27 @@ static bool TryCreateProvider(
return true;
}

static SerilogLoggerProvider CreateProvider(
IConfiguration configuration,
string defaultServerUrl,
string defaultApiKey)
{
string serverUrl = null, apiKey = null;
if (configuration != null)
{
serverUrl = configuration["ServerUrl"];
apiKey = configuration["ApiKey"];
}

if (string.IsNullOrWhiteSpace(serverUrl))
serverUrl = defaultServerUrl;

if (string.IsNullOrWhiteSpace(apiKey))
apiKey = defaultApiKey;

return CreateProvider(serverUrl, apiKey, LevelAlias.Minimum, null);
}

static SerilogLoggerProvider CreateProvider(
string serverUrl,
string apiKey,
Expand Down
17 changes: 1 addition & 16 deletions src/Seq.Extensions.Logging/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Seq.Extensions.Logging")]
[assembly: AssemblyTrademark("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Seq.Extensions.Logging.Tests, PublicKey=" +
"00240000048000009400000006020000002400005253413100040000010001003181403962b35f" +
Expand Down
44 changes: 7 additions & 37 deletions src/Seq.Extensions.Logging/Seq.Extensions.Logging.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,24 @@

<PropertyGroup>
<Description>Add centralized structured log collection to ASP.NET Core apps with one line of code.</Description>
<VersionPrefix>4.0.2</VersionPrefix>
<VersionPrefix>5.0.0</VersionPrefix>
<Authors>Datalust and Contributors</Authors>
<TargetFrameworks>net45;net46;net461;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net462;netstandard2.0</TargetFrameworks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>Seq.Extensions.Logging</AssemblyName>
<AssemblyOriginatorKeyFile>../../asset/seqext.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>Seq.Extensions.Logging</PackageId>
<PackageTags>asp.net;core;logging</PackageTags>
<PackageTags>aspnet;logging</PackageTags>
<PackageIconUrl>https://datalust.co/images/nuget/seq.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/datalust/seq-extensions-logging</PackageProjectUrl>
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="1.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="2.1.0" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net46' or '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net461' or '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net46' or '$(TargetFramework)' == 'net461'">
<Reference Include="System.Net.Http" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' ">
<DefineConstants>$(DefineConstants);REMOTING;THREADING_TIMER;WAITABLE_TIMER;HRESULTS</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net46' or '$(TargetFramework)' == 'netstandard1.3' ">
<DefineConstants>$(DefineConstants);ASYNCLOCAL</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net461' or '$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>$(DefineConstants);ASYNCLOCAL;LOGGING_BUILDER</DefineConstants>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
#if ASYNCLOCAL
using System.Threading;
#else
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
#endif
using Microsoft.Extensions.Logging;
using Serilog.Core;
using Serilog.Events;
Expand All @@ -19,9 +14,7 @@ namespace Serilog.Extensions.Logging
/// <summary>
/// An <see cref="ILoggerProvider"/> that pipes events through Serilog.
/// </summary>
#if LOGGING_BUILDER
[ProviderAlias("Seq")]
#endif
class SerilogLoggerProvider : ILoggerProvider, ILogEventEnricher
{
internal const string OriginalFormatPropertyName = "{OriginalFormat}";
Expand Down Expand Up @@ -77,27 +70,13 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
}
}

#if ASYNCLOCAL
readonly AsyncLocal<SerilogLoggerScope> _value = new AsyncLocal<SerilogLoggerScope>();

internal SerilogLoggerScope CurrentScope
{
get => _value.Value;
set => _value.Value = value;
}
#else
readonly string _currentScopeKey = nameof(SerilogLoggerScope) + "#" + Guid.NewGuid().ToString("n");

internal SerilogLoggerScope CurrentScope
{
get
{
var objectHandle = CallContext.LogicalGetData(_currentScopeKey) as ObjectHandle;
return objectHandle?.Unwrap() as SerilogLoggerScope;
}
set => CallContext.LogicalSetData(_currentScopeKey, new ObjectHandle(value));
}
#endif

/// <inheritdoc />
public void Dispose()
Expand Down
Loading