Output Diagnostic Source to Event Source
At the beginning
Previously described DiagnosticSource, but DiagnosticSource only provides a mechanism for event occurrence and capture of that event, so how do you finally output it? Whether or not to do so is largely at the discretion of the user.
The standard method is to subscribe to DiagnosticListener.AllListeners and output it, but here I will describe how to output it through EventSource.
Please note that this article is based on .NET 5.0-rc1, so the specifications may change in future releases.
What is EventSource?
As mentioned in DiagnosticSource article, it is like a senior of DiagnosticSource and has existed since the .NET Framework era.
Originally it was a mechanism that got on ETW, but in order to make it cross-platform, a mechanism called EventPipe has been used from .NET Core 3.0, and it can be used without restrictions regardless of OS.
The advantage over DiagnosticSource is that it has a mechanism for collecting information from the outside, so it is possible to collect information later. (Example: dotnet-trace, Application Insights (Azure) etc.)
There is no document that the mechanism of EventPipe etc. is like this, but for individual IPC protocols etc. documentation of dotnet / diagnostics repository, So if you want to know more details, click here (it seems that you can connect via a named pipe on win and a unix domain socket on linux).
If you do your best, you can also make your own output mechanism.
This area is documents of client library of dotnet / diagnostics and Documentation about parser provided by perfview may be helpful. ..
DiagnosticSource cannot be collected directly, but DiagnosticSource has a function to output events with EventSource, so event information can be acquired through it.
Preparation
First, suppose you have the following Diagnostic Source
// using System.Diagnostics;
class C1
{
public DiagnosticSource _D = new DiagnosticListener("Diag1");
public void A()
{
if(_D.IsEnabled("ev1"))
{
_D.Write("ev1", new { X = "str" });
}
}
}
In this way, the event “ev1” will be fired when C1.A ()
is executed.
Then, create a process that executes this C1.A ()
on the ** app side of ** netcore app3.0 or later.
class Program
{
static void Main(string[] args)
{
while(true)
{
//Once a second"ev1"Event occurs
new C1().A();
Task.Delay(1000).Wait();
}
}
}
This is all the preparation. No additional implementation is required on the app side.
Collection of events
All DiagnosticSource events are output from a provider called Microsoft-Diagnostics-DiagnosticSource
(internally ʻEventSource.Name`).
Therefore, the collection tool side specifies this name as the EventPipe Provider and collects.
Parameters that can be specified at the start of monitoring include
- Event level to monitor
- Event keywords to monitor
- Additional parameters
There is.
The event level is fixed at ʻEventLevel.Informational`.
Event keywords will be described later.
As an additional parameter, there is “FilterAndPayloadSpec” that filters events, etc., but this will be described later because the specifications are complicated.
Event keyword flag
A bit flag set for the event to be collected, with a hexadecimal number (up to 8 digits)
The following keyword flags exist in Microsoft-Diagnostics-DiagnosticSource
name | Numerical value | Overview |
---|---|---|
Messages | 0x1 | Other debug messages |
Events | 0x2 | Event occurrence from Diagnostic Source or Activity Source |
IgnoreShortCutKeywords | 0x800 | When true, ignore the following two keywords |
AspNetCoreHosting | 0x1000 | ASP to collect.Add .NET Core related events |
EntityFrameworkCoreCommands | 0x2000 | Add EFCore related events to the collection target |
There is no problem if you include Events in the amount you normally use.
Events added by AspNetCoreHosting
- Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.BeginRequest@Activity1Start
- Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.EndRequest@Activity1Stop
See “About FilterAndPayloadSpec” below for this format.
Events added by EntityFrameworkCoreCommands
- Microsoft.EntityFrameworkCore/Microsoft.EntityFrameworkCore.BeforeExecuteCommand@Activity1Start
- Microsoft.EntityFrameworkCore/Microsoft.EntityFrameworkCore.AfterExecuteCommand@Activity1Stop
See “About FilterAndPayloadSpec” below for this format.
Additional parameters
So far only FilterAndPayloadSpec
, but this is quite complicated. Unless otherwise specified, it means “capture all DiagnosticSource events, not ActivitySource”.
About FilterAndPayloadSpec
Set which event to monitor and how to interpret the data generated by the event.
Unless otherwise specified, it means “capture all DiagnosticSource events, not ActivitySource”.
This is a very basic one, so if you want to know more, you can use [Actual DiagnosticSourceEventSource Source](https://github.com/dotnet/runtime/blob/v5.0.0-rc.1.20451. It’s a good idea to check (14 / src / libraries / System.Diagnostics.DiagnosticSource / src / System / Diagnostics / DiagnosticSourceEventSource.cs).
Basic format
Specifies what events to capture and how to interpret the parameters of the captured events
In the case of DiagnosticSource, the format is [DiagnosticSource name] / [event name] @ [EventSource name]: [conversion destination parameter name] = [conversion source parameter name]; ]
to specify.
It’s long to write everything, but all you need is the name of the Diagnostic Source.
Specifying Diagnostic Source
The one specified by [DiagnositicSource name]
is included in the capture target. Use the name DiagnosticSource.Name
here.
event name
Enter the name specified by DiagnosticSource.Write
here.
The [EventSource name]
part is a little difficult to understand, but by writing ʻActivity1Start etc., it means that the event is captured as ʻActivity1Start
. If there is no description around here, all events are processed as event ID = 2, event name = " [Activity name]. [Start or Stop] "
.
Describe this with ** CRLF delimiter ** for each Diagnostic Source.
So if you want to detect both Diag1
and Diag2
,
Diag1<CRLF>
Diag2
Set the parameters as follows. If it is programmatic, it can be set with StringBuilder, but be careful if you want to specify it on the command line.
Also, the ActivitySource event cannot be captured by default, but if you want to add an ActivitySource event, add [AS]
to the beginning of the same parameter.
At this time, if you specify [AS] *
as a special notation, it is possible to capture all Activity Source events.
As an example, if you want to add an ActivitySource called ʻAct1`,
[AS]Act1
Describe as.
Event level
The event level of Microsoft-Diagnostics-Diagnostic Source introduced this time is fixed to Informational,
The following is a list of other things.
- Critial = 1
- Error = 2
- Warning = 3
- Informational = 4
- Verbose = 5
- LogAlways = 0
See the official documentation (https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.tracing.eventlevel) for the exact reference.
Events that occur in Microsoft-Diagnostics-DiagnosticSource
Event ID | event name | Event keywords | Overview |
---|---|---|---|
1 | Message | Messages | Other messages |
2 | Event | Events | DiagnosticSource.Write Events that occur in |
3 | EventJson | Events | Same as Event, but occurs only on net45 and event parameters are jsonized |
4 | Activity1Start | Events | DiagnosticSource.StartActivity Event that occurs when |
5 | Activity1Stop | Events | DiagnosticSource.StopActivity Event that occurs when |
6 | Activity2Start | Events | DiagnosticSource.StartActivity Event that occurs when |
7 | Activity2Stop | Events | DiagnosticSource.StopActivity Event that occurs when |
8 | RecursiveActivity1Start | Events | Events that occur when a nested Activity is started |
9 | RecursiveActivity1Stop | Events | Events that occur when a nested Activity ends |
10 | NewDiagnosticListener | Events | Events that occur when a DiagnosticListener is added |
11 | ActivityStart | Events | Event that occurs when Activity starts in ActivitySource |
12 | ActivityStop | Events | Event that occurs when Activity ends in ActivitySource |
Collection by dotnet-trace
There are various ways to capture the output of EventSource, but here we will introduce the method by dotnet-trace.
Introduction of tools
It is provided as a dotnet tool, so you can install dotnet-sdk and install it with dotnet tool install -g dotnet-trace
(you need to pass the path to $ HOME / .dotnet / tools
)
Collection of events
Collect information as follows:
- Launch the app
- Get PID
- In addition to OS commands (
tasklist
andps
), you can also get PID withdotnet-trace ps
.
- In addition to OS commands (
dotnet-trace collect -p [PID] [Other options] --providers" Microsoft-Diagnostics-DiagnosticSource [Additional options] "
to start collecting- By default, all event information of DiagnosticSource is output.
- Stop collecting with Ctrl-C or Enter
The above will generate a trace file that records event information (default is trace.net trace
).
Note that ** Since there is no function to start monitoring as soon as the application is started, it may not be possible to acquire event logs at startup **
The format of the additional option is [event keyword]: [event level]: [additional parameter specified in K = V format]
How to pass to providers option
Since FilterAndPayloadSpecs includes line breaks, it may be difficult to pass a value depending on the shell.
Since dotnet-trace uses the framework of System.CommandLine for the application execution platform, it can be read using the response file. Yes](https://github.com/dotnet/command-line-api/blob/main/docs/Features-overview.md#Response-files).
First, prepare the following text file
--providers
Microsoft-Diagnostics-DiagnosticSource:[Event keywords]:[Event level]:FilterAndPayloadSpecs=[What you want to pass to FilterAndPayloadSpecs]
Line breaks can be represented by \ r \ n
.
Once the file is ready, execute it as follows.
dotnet trace collect -p [PID] "@[Path to file]"
Viewing event information
Event information can be viewed at Perfview. Perfview is for Windows only, but it can also be converted to chromium trace file format (Chromium) or SpeedScope format, so you can view logs on Linux. However, note that the primary format is nettrace, so the other two formats may lack information.
At the end
In fact, I think that Diagnostic Source and Activity Source will be used indirectly through more user-friendly libraries such as opentelemetry rather than directly. But I think it’s good to have an ad hoc way to get information when something goes wrong.
Later, I personally think that ActivitySource should have a separate EventSource.
Reference article
- dotnet-trace
- DiagnosticSourceEventSource
- Detailed parameter description etc.
- dotnet / diagnostics repository
- EventPipe specifications, dotnet-trace source, etc.