Skip to content

Commit

Permalink
Introduce Elastic.Serilog.Enrichers.Web (#444)
Browse files Browse the repository at this point in the history
Fixes: #343

---------

Co-authored-by: Steve Gordon <[email protected]>
  • Loading branch information
Mpdreamz and stevejgordon authored Sep 24, 2024
1 parent 6f15e7c commit 4108bf9
Show file tree
Hide file tree
Showing 18 changed files with 144 additions and 84 deletions.
7 changes: 5 additions & 2 deletions build/scripts/Targets.fs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ let private validatePackages (arguments: ParseResults<Arguments>) =

let nugetPackages =
Paths.Output.GetFiles("*.nupkg")
|> Seq.sortByDescending (fun f -> f.CreationTimeUtc)
|> Seq.sortByDescending (_.CreationTimeUtc)
//skipping because system web fullframework not able to validate
|> Seq.filter (fun f -> not <| f.Name.StartsWith("Elastic.Serilog.Enrichers.Web."))
|> Seq.map (fun p -> Paths.RootRelative p.FullName)

let ciOnWindowsArgs = if runningOnCI && runningOnWindows then [ "-r"; "true" ] else []
Expand Down Expand Up @@ -285,7 +287,8 @@ let Setup (parsed: ParseResults<Arguments>) (subCommand: Arguments) =

cmd
Release.Name
(Some [ PristineCheck.Name; Test.Name; Integrate.Name ])
None
// (Some [ PristineCheck.Name; Test.Name; Integrate.Name ])
(Some [ GeneratePackages.Name; ValidatePackages.Name; GenerateReleaseNotes.Name; GenerateApiChanges.Name ])
<| fun _ -> release parsed

Expand Down
8 changes: 8 additions & 0 deletions ecs-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,11 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Extensions.Logging.Console.Example", "examples\Elastic.Extensions.Logging.Console.Example\Elastic.Extensions.Logging.Console.Example.csproj", "{9656A08E-9DA6-473A-B3F8-245AC7B81A28}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Extensions.Logging.Common", "src\Elastic.Extensions.Logging.Common\Elastic.Extensions.Logging.Common.csproj", "{5EDF109F-9DFF-4957-8864-BA2702FB78F6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Serilog.Sinks.Tests", "tests\Elastic.Serilog.Sinks.Tests\Elastic.Serilog.Sinks.Tests.csproj", "{933FD923-A2DC-49E3-B21E-8BA888DB5924}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Serilog.Enrichers.Web", "src\Elastic.Serilog.Enrichers.Web\Elastic.Serilog.Enrichers.Web.csproj", "{B6DCC4C4-1287-41BE-A19D-8F311C6E39F7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -304,6 +307,10 @@ Global
{933FD923-A2DC-49E3-B21E-8BA888DB5924}.Debug|Any CPU.Build.0 = Debug|Any CPU
{933FD923-A2DC-49E3-B21E-8BA888DB5924}.Release|Any CPU.ActiveCfg = Release|Any CPU
{933FD923-A2DC-49E3-B21E-8BA888DB5924}.Release|Any CPU.Build.0 = Release|Any CPU
{B6DCC4C4-1287-41BE-A19D-8F311C6E39F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6DCC4C4-1287-41BE-A19D-8F311C6E39F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6DCC4C4-1287-41BE-A19D-8F311C6E39F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6DCC4C4-1287-41BE-A19D-8F311C6E39F7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -350,6 +357,7 @@ Global
{9656A08E-9DA6-473A-B3F8-245AC7B81A28} = {05075402-8669-45BD-913A-BD40A29BBEAB}
{5EDF109F-9DFF-4957-8864-BA2702FB78F6} = {7610B796-BB3E-4CB2-8296-79BBFF6D23FC}
{933FD923-A2DC-49E3-B21E-8BA888DB5924} = {3582B07D-C2B0-49CC-B676-EAF806EB010E}
{B6DCC4C4-1287-41BE-A19D-8F311C6E39F7} = {7610B796-BB3E-4CB2-8296-79BBFF6D23FC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7F60C4BB-6216-4E50-B1E4-9C38EB484843}
Expand Down
2 changes: 1 addition & 1 deletion examples/aspnetcore-with-serilog/AspnetCoreExample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Elastic.Apm.SerilogEnricher\Elastic.Apm.SerilogEnricher.csproj" />
<ProjectReference Include="..\..\src\Elastic.CommonSchema.Serilog\Elastic.CommonSchema.Serilog.csproj" />
<ProjectReference Include="..\..\src\Elastic.Serilog.Enrichers.Web\Elastic.Serilog.Enrichers.Web.csproj" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions examples/aspnetcore-with-serilog/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.IO;
using Elastic.Apm.SerilogEnricher;
using Elastic.CommonSchema.Serilog;
using Elastic.Serilog.Enrichers.Web;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.302",
"version": "8.0.100",
"rollForward": "latestFeature",
"allowPrerelease": false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Elastic.CommonSchema.Serilog
public interface IEcsTextFormatterConfiguration : IEcsDocumentCreationOptions
{
/// <summary>
/// Expert option, its recommended to use <see cref="EnricherExtensions.WithEcsHttpContext"/> to ensure HttpContext gets mapped
/// Expert option: Installing <c>Elastic.Serilog.Enrichers.Web</c> is recommended to ensure HttpContext gets mapped.
/// to the appropriate ECS fields.
/// <para> Example: </para>
/// <code>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,11 @@
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Remove="Lib\UAParser.regexes.yaml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Lib\UAParser.regexes.yaml">
<LogicalName>UAParser.regexes.yaml</LogicalName>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Elastic.CommonSchema\Elastic.CommonSchema.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="2.9.0.0" />
<PackageReference Condition="$(DefineConstants.Contains(NETSTANDARD))" Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.1.0.0" />
<PackageReference Condition="$(DefineConstants.Contains(NETSTANDARD))" Include="Microsoft.AspNetCore.Http.Extensions" Version="2.1.0.0" />
<Reference Condition="$(DefineConstants.Contains(FULLFRAMEWORK))" Include="System.Web" />
<PackageReference Include="PolySharp" Version="1.13.2" PrivateAssets="all">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
11 changes: 6 additions & 5 deletions src/Elastic.CommonSchema.Serilog/LogEventConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Serilog.Events;
using static Elastic.CommonSchema.Serilog.SpecialProperties;

namespace Elastic.CommonSchema.Serilog
{
Expand Down Expand Up @@ -312,7 +313,7 @@ void Assign(string key, Action<Agent, string> assign)
private static Http? GetHttp(LogEvent e, IEcsTextFormatterConfiguration configuration)
{
if (e.TryGetScalarPropertyValue(SpecialKeys.HttpContext, out var httpContext)
&& httpContext.Value is HttpContextEnricher.HttpContextEnrichments enriched)
&& httpContext.Value is HttpContextEnrichments enriched)
return enriched.Http;

var http = configuration.MapHttpAdapter?.Http;
Expand Down Expand Up @@ -346,7 +347,7 @@ void Assign(string key, Action<Agent, string> assign)
private static Url? GetUrl(LogEvent e, IEcsTextFormatterConfiguration configuration)
{
if (e.TryGetScalarPropertyValue(SpecialKeys.HttpContext, out var httpContext)
&& httpContext.Value is HttpContextEnricher.HttpContextEnrichments enriched)
&& httpContext.Value is HttpContextEnrichments enriched)
return enriched.Url;

var url = configuration.MapHttpAdapter?.Url;
Expand Down Expand Up @@ -375,7 +376,7 @@ void Assign(string key, Action<Agent, string> assign)
private static UserAgent? GetUserAgent(LogEvent e, IEcsTextFormatterConfiguration configuration)
{
if (e.TryGetScalarPropertyValue(SpecialKeys.HttpContext, out var httpContext)
&& httpContext.Value is HttpContextEnricher.HttpContextEnrichments enriched)
&& httpContext.Value is HttpContextEnrichments enriched)
return enriched.UserAgent;

return configuration.MapHttpAdapter?.UserAgent;
Expand All @@ -384,7 +385,7 @@ void Assign(string key, Action<Agent, string> assign)
private static User? GetUser(LogEvent e, IEcsTextFormatterConfiguration configuration)
{
if (e.TryGetScalarPropertyValue(SpecialKeys.HttpContext, out var httpContext)
&& httpContext.Value is HttpContextEnricher.HttpContextEnrichments enriched)
&& httpContext.Value is HttpContextEnrichments enriched)
return enriched.User;

return configuration.MapHttpAdapter?.User;
Expand All @@ -393,7 +394,7 @@ void Assign(string key, Action<Agent, string> assign)
private static Client? GetClient(LogEvent e, IEcsTextFormatterConfiguration configuration)
{
if (e.TryGetScalarPropertyValue(SpecialKeys.HttpContext, out var httpContext)
&& httpContext.Value is HttpContextEnricher.HttpContextEnrichments enriched)
&& httpContext.Value is HttpContextEnrichments enriched)
return enriched.Client;

return configuration.MapHttpAdapter?.Client;
Expand Down
37 changes: 0 additions & 37 deletions src/Elastic.CommonSchema.Serilog/SpecialKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,3 @@

namespace Elastic.CommonSchema.Serilog;

internal static class SpecialKeys
{
public const string DefaultLogger = "Elastic.CommonSchema.Serilog";

public const string SourceContext = nameof(SourceContext);
public const string EnvironmentUserName = nameof(EnvironmentUserName);
public const string Host = nameof(Host);
public const string ActionCategory = nameof(ActionCategory);
public const string ActionName = nameof(ActionName);
public const string ActionId = nameof(ActionId);
public const string ActionKind = nameof(ActionKind);
public const string ActionSeverity = nameof(ActionSeverity);
public const string EventId = nameof(EventId);
public const string ApplicationId = nameof(ApplicationId);
public const string ApplicationName = nameof(ApplicationName);
public const string ApplicationType = nameof(ApplicationType);
public const string ApplicationVersion = nameof(ApplicationVersion);
public const string ProcessName = nameof(ProcessName);
public const string ProcessId = nameof(ProcessId);
public const string ThreadId = nameof(ThreadId);
public const string MachineName = nameof(MachineName);
public const string Elapsed = nameof(Elapsed);
public const string ElapsedMilliseconds = nameof(ElapsedMilliseconds);
public const string Method = nameof(Method);
public const string RequestMethod = nameof(RequestMethod);
public const string Path = nameof(Path);
public const string RequestPath = nameof(RequestPath);
public const string StatusCode = nameof(StatusCode);
public const string Scheme = nameof(Scheme);
public const string ContentType = nameof(ContentType);
public const string QueryString = nameof(QueryString);
public const string RequestId = nameof(RequestId);
public const string HttpContext = nameof(HttpContext);

// a known ASP.NET key we don't want to emit under labels.*
public const string HostingRequestFinishedLog = nameof(HostingRequestFinishedLog);
}
54 changes: 54 additions & 0 deletions src/Elastic.CommonSchema.Serilog/SpecialProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
namespace Elastic.CommonSchema.Serilog;

/// <summary> Defines known keys and types to read from serilog properties </summary>
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public static class SpecialProperties
{
public class HttpContextEnrichments
{
public Client? Client { get; set; }
public Http? Http { get; set; }
public Server? Server { get; set; }
public Url? Url { get; set; }
public User? User { get; set; }
public UserAgent? UserAgent { get; set; }
}

public static class SpecialKeys
{
public const string DefaultLogger = "Elastic.CommonSchema.Serilog";

public const string SourceContext = nameof(SourceContext);
public const string EnvironmentUserName = nameof(EnvironmentUserName);
public const string Host = nameof(Host);
public const string ActionCategory = nameof(ActionCategory);
public const string ActionName = nameof(ActionName);
public const string ActionId = nameof(ActionId);
public const string ActionKind = nameof(ActionKind);
public const string ActionSeverity = nameof(ActionSeverity);
public const string EventId = nameof(EventId);
public const string ApplicationId = nameof(ApplicationId);
public const string ApplicationName = nameof(ApplicationName);
public const string ApplicationType = nameof(ApplicationType);
public const string ApplicationVersion = nameof(ApplicationVersion);
public const string ProcessName = nameof(ProcessName);
public const string ProcessId = nameof(ProcessId);
public const string ThreadId = nameof(ThreadId);
public const string MachineName = nameof(MachineName);
public const string Elapsed = nameof(Elapsed);
public const string ElapsedMilliseconds = nameof(ElapsedMilliseconds);
public const string Method = nameof(Method);
public const string RequestMethod = nameof(RequestMethod);
public const string Path = nameof(Path);
public const string RequestPath = nameof(RequestPath);
public const string StatusCode = nameof(StatusCode);
public const string Scheme = nameof(Scheme);
public const string ContentType = nameof(ContentType);
public const string QueryString = nameof(QueryString);
public const string RequestId = nameof(RequestId);
public const string HttpContext = nameof(HttpContext);

// a known ASP.NET key we don't want to emit under labels.*
public const string HostingRequestFinishedLog = nameof(HostingRequestFinishedLog);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

#if NETSTANDARD
using System.Linq;
#if NET
using System.Security.Claims;
using Elastic.CommonSchema;
using Elastic.CommonSchema.Serilog.Adapters;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Http.Features;
using UAParser;
using UserAgent = Elastic.CommonSchema.UserAgent;

namespace Elastic.CommonSchema.Serilog.Adapters
namespace Elastic.Serilog.Enrichers.Web.Adapters
{
/// <inheritdoc cref="IHttpAdapter"/>
public class HttpAdapter : IHttpAdapter
Expand Down Expand Up @@ -112,7 +114,7 @@ public Url? Url
Original = request.GetDisplayUrl(),
Full = request.GetDisplayUrl(),
Scheme = request.Scheme,
Query = request.QueryString.HasValue ? request.QueryString.Value.TrimStart('?') : null,
Query = request.QueryString.HasValue ? request.QueryString.Value?.TrimStart('?') : null,
Domain = request.Host.HasValue ? request.Host.Host : null,
Port = request.Host.HasValue ? request.Host.Port : null
};
Expand All @@ -127,14 +129,14 @@ public Server? Server
if (_httpContextAccessor?.HttpContext == null)
return null;

var ip4 = _httpContextAccessor.HttpContext.Connection.LocalIpAddress.MapToIPv4();
var ip4 = _httpContextAccessor.HttpContext.Connection.LocalIpAddress?.MapToIPv4();

var request = _httpContextAccessor.HttpContext.Request;

return new Server
{
Address = ip4.ToString(),
Ip = ip4.ToString(),
Address = ip4?.ToString(),
Ip = ip4?.ToString(),
Domain = request.Host.HasValue ? request.Host.Host : null
};
}
Expand All @@ -148,7 +150,7 @@ public Client? Client
if (_httpContextAccessor?.HttpContext == null)
return null;

var ip4 = _httpContextAccessor.HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress.MapToIPv4();
var ip4 = _httpContextAccessor.HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress?.MapToIPv4();

return new Client
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

#if !NETSTANDARD
#if FULLFRAMEWORK
using Elastic.CommonSchema;
using Elastic.CommonSchema.Serilog.Adapters;
using System.Web;

namespace Elastic.CommonSchema.Serilog.Adapters
namespace Elastic.Serilog.Enrichers.Web.Adapters
{
/// <inheritdoc cref="IHttpAdapter"/>
public class HttpAdapter : IHttpAdapter
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net8.0;net461</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Title>Elastic Common Schema (ECS) Serilog Enricher for Web proeprties</Title>
<Description>Serilog enricher for ASP.NET (Core) to inject more data in emitted Elastic Common Schema (ECS) documents.</Description>
<IsPackable>True</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Elastic.CommonSchema.Serilog\Elastic.CommonSchema.Serilog.csproj" />
<ProjectReference Include="..\Elastic.CommonSchema\Elastic.CommonSchema.csproj"/>
</ItemGroup>
<ItemGroup>
<FrameworkReference Condition="$(DefineConstants.Contains(NETCOREAPP))" Include="Microsoft.AspNetCore.App"/>
<Reference Condition="$(DefineConstants.Contains(FULLFRAMEWORK))" Include="System.Web" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Serilog" Version="2.9.0.0"/>
</ItemGroup>

<ItemGroup>
<None Remove="Lib\UAParser.regexes.yaml" />
<EmbeddedResource Include="Lib\UAParser.regexes.yaml" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System;
using Serilog;
using Serilog.Configuration;
#if NETSTANDARD
#if NET
using Microsoft.AspNetCore.Http;
#endif

namespace Elastic.CommonSchema.Serilog;
namespace Elastic.Serilog.Enrichers.Web;

/// <summary>
/// <see cref="LoggerEnrichmentConfiguration"/> Extensions to register ECS enrichers
/// </summary>
public static class EnricherExtensions
{
#if NETSTANDARD
#if NET
/// <summary>Include current HTTP context data on any ECS document created</summary>
/// <param name="enrichmentConfiguration">Logger enrichment configuration.</param>
/// <param name="httpContextAccessor"></param>
Expand Down
Loading

0 comments on commit 4108bf9

Please sign in to comment.