Skip to content

Commit 62dc4ea

Browse files
committed
Renaming and documenting.
1 parent 955fbb4 commit 62dc4ea

9 files changed

Lines changed: 61 additions & 32 deletions

File tree

Diagnostics/PostSharp.Samples.Logging.ElasticStack/ClientExample/ClientExample.csproj renamed to Diagnostics/PostSharp.Samples.Logging.ElasticStack/ClientExample/PostSharp.Samples.Logging.Distributed.Client.csproj

File renamed without changes.

Diagnostics/PostSharp.Samples.Logging.ElasticStack/ClientExample/Program.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ public static class Program
1919

2020
private static async Task Main()
2121
{
22-
HttpClientLogging.Initialize( uri => uri.Port != 9200 );
22+
2323

24+
// Configure Serilog to write to the console and to Elastic Search.
2425
using (var logger = new LoggerConfiguration()
2526
.Enrich.WithProperty("Application", "Client")
2627
.MinimumLevel.Debug()
@@ -37,6 +38,8 @@ private static async Task Main()
3738
"{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] {Indent:l}{Message:l}{NewLine}{Exception}")
3839
.CreateLogger())
3940
{
41+
42+
// Configure PostSharp Logging to write to Serilog.
4043
var backend = new SerilogLoggingBackend(logger);
4144
backend.Options.IncludeActivityExecutionTime = true;
4245
backend.Options.IncludeExceptionDetails = true;
@@ -45,6 +48,9 @@ private static async Task Main()
4548
backend.Options.ContextIdGenerationStrategy = ContextIdGenerationStrategy.Hierarchical;
4649
LoggingServices.DefaultBackend = backend;
4750

51+
// Intercept outgoing HTTP requests and add logging to them.
52+
HttpClientLogging.Initialize(uri => uri.Port != 9200);
53+
4854

4955
using (logSource.Debug.OpenActivity(Formatted("Running the client"),
5056
new OpenActivityOptions(new Baggage { User = "Gaius Julius Caesar" })))
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# PostSharp.Samples.Logging.ElasticStack: ClientExample
22

3-
This is the client side of the PostSharp.Samples.Logging.ElasticStack example.
3+
This is the client-side of the PostSharp.Samples.Logging.ElasticStack example.
44

5-
The *InstrumentOutgoingRequestsAspect* aspect is the most interesting part of this project. It instruments the HttpClient class. It basically does three things:
5+
A few interesting points:
66

7-
* Open a client-side activity (aka context), which emits log client-side records into Elastic Search.
8-
* Set the `Request-Id` header of the outgoing HTTP request to the `SyntheticId` of the newly created activity.
9-
* Set the `Correlation-Context` header ot the outgoing HTTP request to the baggage (i.e. cross-process properties). In this example, we've set a cross-process property named `User` in `Program.Main`.
7+
* Serilog is configured to write to the console and to Elastic Search (actually logstash).
8+
* PostSharp Logging is configured to write to Serilog.
9+
* The call to `HttpClientLogging.Initialize()` adds logging to outgoing HTTP requests, but also adds the headers that are required for distributed logging.
10+
* The top-level custom attribute `[assembly: Log]` adds logging to every single method in the current project.

Diagnostics/PostSharp.Samples.Logging.ElasticStack/MicroserviceExample/MicroserviceExample.csproj renamed to Diagnostics/PostSharp.Samples.Logging.ElasticStack/MicroserviceExample/PostSharp.Samples.Logging.Distributed.Service.csproj

File renamed without changes.

Diagnostics/PostSharp.Samples.Logging.ElasticStack/MicroserviceExample/Program.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public class Program
2020

2121
public static void Main(string[] args)
2222
{
23-
AspNetCoreLogging.Initialize();
2423

24+
// Configure Serilog to write to the console and to Elastic Search.
2525
using (var logger = new LoggerConfiguration()
2626
.Enrich.WithProperty("Application", "Microservice")
2727
.MinimumLevel.Debug()
@@ -39,7 +39,7 @@ public static void Main(string[] args)
3939
.CreateLogger())
4040
{
4141

42-
42+
// Configure PostSharp Logging to write to Serilog.
4343
var backend = new SerilogLoggingBackend(logger);
4444
backend.Options.IncludeActivityExecutionTime = true;
4545
backend.Options.IncludeExceptionDetails = true;
@@ -53,6 +53,10 @@ public static void Main(string[] args)
5353
LoggingServices.Formatters.Register(new ObjectResultFormatter());
5454

5555

56+
// Instrument ASP.NET Core.
57+
AspNetCoreLogging.Initialize();
58+
59+
5660
// Execute the web app.
5761
CreateWebHostBuilder(args).Build().Run();
5862

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
# PostSharp.Samples.Logging.ElasticStack: MicroserviceExample
22

3-
This is the server side of the PostSharp.Samples.Logging.ElasticStack example.
3+
This is the server-side of the PostSharp.Samples.Logging.ElasticStack example.
44

5-
There are two interesting artifacts in this project:
5+
A few interesting points:
66

7-
* *LoggingActionFilter* is an ASP.NET Action Filter, i.e. it runs before the control flow is given to your code in the controller classes. This action filter does the "opposite" of the *InstrumentOutgoingRequestsAspect* server-side aspect, i.e. it creates a new server-side logging activity (aka context) and assigns:
8-
9-
* the `SyntheticParentId` property to the value of the `Request-Id` HTTP header sent by the client, and
10-
* custom properties based on the parsing of the `Correlation-Context` HTTP header.
11-
12-
* *SampledLoggingActionFilter* is another ASP.NET Action Filter which enables logging for a random 10% subset of incoming requests. The default level, for the remaining 90% of requests, is set to Warning in `Program.Main`.
7+
* Serilog is configured to write to the console and to Elastic Search (actually logstash).
8+
* PostSharp Logging is configured to write to Serilog.
9+
* The call to `AspNetCoreLogging.Initialize()` adds logging to the ASP.NET Core stack.
10+
* The top-level custom attribute `[assembly: Log]` adds logging to every single method in the current project.

Diagnostics/PostSharp.Samples.Logging.ElasticStack/README.md

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Serilog and the Elastic Stack
1+
# PostSharp Logging, Serilog and the Elastic Stack
22

33
## Table of contents
44

@@ -13,33 +13,52 @@
1313

1414
## Credits
1515

16-
This example is forked from https://github.com/FantasticFiasco/serilog-sinks-http-sample-elastic-stack. All credits for integrating Elastic Stack with Serilog go to the original authors.
16+
This example is forked from https://github.com/FantasticFiasco/serilog-sinks-http-sample-elastic-stack.
17+
All credits for integrating Elastic Stack with Serilog go to the original authors.
1718

18-
The `elastic-stack` directory is a clone of [docker-elk](https://github.com/deviantony/docker-elk) with minor modifications done by FantasticFiasco. Credit to [deviantony](https://github.com/deviantony) for publishing the Elastic Stack boilerplate.
19+
The `elastic-stack` directory is a clone of [docker-elk](https://github.com/deviantony/docker-elk) with minor modifications done by FantasticFiasco.
20+
Credit to [deviantony](https://github.com/deviantony) for publishing the Elastic Stack boilerplate.
1921

2022
## Introduction
2123

22-
[Elastic Stack](https://www.elastic.co/products) is fantastic at collecting and visualizing log events. [Serilog](https://serilog.net/) is fantastic at producing structured log events. [PostSharp Diagnostics](https://www.postsharp.net/diagnostics)
23-
is fantastic at instrumenting your project and feeding Serilog with plently structured log events.
24+
This example shows how to combine PostSharp Logging, Serilog and the Elastic Stack to achieve logging of a distributed application:
2425

25-
This repository provides a sandbox where developers can explore the life of a log event starting with its birth in PostSharp and Serilog, its transport over the network to Logstash, its fields being indexed by Elasticsearch and finally its legacy being recorded as a historical event in Kibana.
26+
* [Elastic Stack](https://www.elastic.co/products) is fantastic at collecting and visualizing log events.
27+
* [Serilog](https://serilog.net/) is fantastic at producing structured log events.
28+
* [PostSharp Logging](https://www.postsharp.net/logging) is fantastic at instrumenting your project and feeding Serilog with plently structured log events.
29+
30+
This repository provides a sandbox where developers can explore the life of a log event starting with its birth in PostSharp and Serilog,
31+
its transport over the network to Logstash, its fields being indexed by Elasticsearch and finally its legacy being recorded as a historical event in Kibana.
2632

2733
This example contains two applications that run together, so we can explore the correlation of requests coming from both apps.
2834

35+
PostSharp Logging and Serilog are initialized in both applications in `Program.Main`.
36+
2937
Correlation is implemented by two artifacts:
3038

31-
* On client-side, `InstrumentOutgoingRequestsAspect`, a PostSharp aspect, adds a header to `HttpClient`.
39+
* On client-side, a call to `HttpClientLogging.Initialize()`, which intercepts calls to `HttpClient` (outgoing HTTP requests) and adds correlation headers.
3240

33-
* On server-side, `LoggingActionFilter`, an ASP.NET Action Filter, reads the header and adds it as a logging property.
41+
* On server-side, a call to `AspNetCoreLogging.Initialize()`, which intercepts incoming HTTP requests and interprets the correlation headers.
42+
43+
If you have an application that acts both as an HTTP client and server, you would need both calls.
3444

3545

3646
## What you will end up with
3747

3848
![alt text](./doc/resources/kibana.png "Kibana rendering log events")
3949

40-
TODO: Update screenshot.
50+
* Automatic logging without boilerplate: your code is completely instrumented and you don't by a just a couple of custom attributes.
51+
52+
* EventId: a synthetic id, cross-process identifier that makes easy to get all traces of a single distributed transaction just by using
53+
the `StartsWith` operator. For instance, in Kibana, try a filter like `fields.EventId: '4b6e6bfaaa.a2.a3.b33.a7*'`.
54+
55+
* User: a baggage property, defined in the client and transported to the server. Try to display `fields.#User`.
56+
57+
58+
You are now ready to take it to the next level.
4159

42-
With a running Elastic Stack and Serilog producing log events you are now ready to take it to the next level. If you fancy the producing part you'll dig deeper into Serilog and its configuration of log contexts, enrichers and message formatters. If you enjoy monitoring applications in production you'll explore Kibana with its visualizations and dashboards.
60+
If you fancy the producing part you'll dig deeper into PostSharp Logging options, custom logging features, and message formatters.
61+
If you enjoy monitoring applications in production you'll explore Kibana with its visualizations and dashboards.
4362

4463
## Requirements
4564

@@ -57,7 +76,8 @@ PS> cd .\elastic-stack\
5776
PS> docker-compose up
5877
```
5978

60-
If this is the first time the stack is started, you'll have to create a Logstash index pattern. Give the stack some time to initialize and then run the following commands in PowerShell:
79+
If this is the first time the stack is started, you'll have to create a Logstash index pattern.
80+
Give the stack some time to initialize, then create the index manually in the UI, or run the following commands in PowerShell:
6181

6282
```posh
6383
PS> $Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
@@ -69,7 +89,7 @@ PS> Invoke-RestMethod "http://localhost:5601/api/saved_objects/index-pattern" `
6989
-Body '{"attributes":{"title":"logstash-*","timeFieldName":"@timestamp"}}'
7090
```
7191

72-
### Publishing log events using PostSharp and Serilog
92+
### Publishing log events using PostSharp Logging
7393

7494
This runs the web service:
7595

273 KB
Loading

PostSharp.Samples.sln

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Aspect Framework", "Aspect
4747
EndProject
4848
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XAML", "XAML", "{0EB69154-BD96-40EF-8404-398B2F956C79}"
4949
EndProject
50-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Diagnostics", "Diagnostics", "{B1F3FAC0-64CB-4CFC-994C-DF56801FC743}"
50+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Logging", "Logging", "{B1F3FAC0-64CB-4CFC-994C-DF56801FC743}"
5151
EndProject
5252
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Threading", "Threading", "{44399EE3-2C8A-4ECE-BC3D-F4D2CA50290F}"
5353
EndProject
@@ -85,14 +85,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostSharp.Samples.Logging.E
8585
EndProject
8686
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostSharp.Samples.NormalizeString", "Framework\PostSharp.Samples.NormalizeString\PostSharp.Samples.NormalizeString.csproj", "{EB412369-CE3D-4D0F-9E16-A93D501DAA1A}"
8787
EndProject
88-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ElasticStack", "ElasticStack", "{6B66C0C7-17E9-4888-826E-0168EBDFC2A7}"
88+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Distributed", "Distributed", "{6B66C0C7-17E9-4888-826E-0168EBDFC2A7}"
8989
ProjectSection(SolutionItems) = preProject
9090
Diagnostics\PostSharp.Samples.Logging.ElasticStack\README.md = Diagnostics\PostSharp.Samples.Logging.ElasticStack\README.md
9191
EndProjectSection
9292
EndProject
93-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientExample", "Diagnostics\PostSharp.Samples.Logging.ElasticStack\ClientExample\ClientExample.csproj", "{D13928C0-62FE-4B93-86BC-E45B147C7C08}"
93+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PostSharp.Samples.Logging.Distributed.Client", "Diagnostics\PostSharp.Samples.Logging.ElasticStack\ClientExample\PostSharp.Samples.Logging.Distributed.Client.csproj", "{D13928C0-62FE-4B93-86BC-E45B147C7C08}"
9494
EndProject
95-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroserviceExample", "Diagnostics\PostSharp.Samples.Logging.ElasticStack\MicroserviceExample\MicroserviceExample.csproj", "{B4216E1F-7FBC-4D5F-AE1A-38E67EC88852}"
95+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PostSharp.Samples.Logging.Distributed.Service", "Diagnostics\PostSharp.Samples.Logging.ElasticStack\MicroserviceExample\PostSharp.Samples.Logging.Distributed.Service.csproj", "{B4216E1F-7FBC-4D5F-AE1A-38E67EC88852}"
9696
EndProject
9797
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PostSharp.Samples.StoredProcedure", "Framework\PostSharp.Samples.StoredProcedure\PostSharp.Samples.StoredProcedure.csproj", "{3142BE72-115D-4733-8ED1-FE80196AF4FE}"
9898
EndProject

0 commit comments

Comments
 (0)