Add ASP.NET Core logging example (#4821)
This commit is contained in:
parent
9139b72128
commit
e9d0e2b035
|
|
@ -30,7 +30,7 @@ repo.
|
|||
|
||||
If you are new here, please read the getting started docs:
|
||||
|
||||
* Logs: [Console](./docs/logs/getting-started-console/README.md)
|
||||
* Logs: [ASP.NET Core](./docs/logs/getting-started-aspnetcore/README.md) | [Console](./docs/logs/getting-started-console/README.md)
|
||||
* Metrics: [ASP.NET Core](./docs/metrics/getting-started-aspnetcore/README.md) |
|
||||
[Console](./docs/metrics/getting-started-console/README.md)
|
||||
* Traces: [ASP.NET Core](./docs/trace/getting-started-aspnetcore/README.md) |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
// <copyright file="Program.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using OpenTelemetry.Logs;
|
||||
using OpenTelemetry.Resources;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Remove default providers and add OpenTelemetry logging provider
|
||||
// For instructional purposes only, disable the default .NET console logging provider to
|
||||
// use the verbose OpenTelemetry console exporter instead. For most development
|
||||
// and production scenarios the default console provider works well and there is no need to
|
||||
// clear these providers.
|
||||
builder.Logging.ClearProviders();
|
||||
|
||||
builder.Logging.AddOpenTelemetry(logging =>
|
||||
{
|
||||
logging.IncludeScopes = true;
|
||||
|
||||
var resourceBuilder = ResourceBuilder
|
||||
.CreateDefault()
|
||||
.AddService(builder.Environment.ApplicationName);
|
||||
|
||||
logging.SetResourceBuilder(resourceBuilder)
|
||||
// ConsoleExporter is used for demo purpose only.
|
||||
// In production environment, ConsoleExporter should be replaced with other exporters (e.g. OTLP Exporter).
|
||||
.AddConsoleExporter();
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapGet("/", (ILogger<Program> logger) =>
|
||||
{
|
||||
logger.FoodPriceChanged("artichoke", 9.99);
|
||||
|
||||
return "Hello from OpenTelemetry Logs!";
|
||||
});
|
||||
|
||||
app.Logger.StartingApp();
|
||||
|
||||
app.Run();
|
||||
|
||||
public static partial class ApplicationLogs
|
||||
{
|
||||
[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Starting the app...")]
|
||||
public static partial void StartingApp(this ILogger logger);
|
||||
|
||||
[LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "Food `{name}` price changed to `{price}`.")]
|
||||
public static partial void FoodPriceChanged(this ILogger logger, string name, double price);
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
# Getting Started with OpenTelemetry .NET Logs in 5 Minutes - ASP.NET Core Application
|
||||
|
||||
First, download and install the [.NET
|
||||
SDK](https://dotnet.microsoft.com/download) on your computer.
|
||||
|
||||
Create a new web application:
|
||||
|
||||
```sh
|
||||
dotnet new web -o aspnetcoreapp
|
||||
cd aspnetcoreapp
|
||||
```
|
||||
|
||||
Install the
|
||||
[OpenTelemetry.Exporter.Console](../../../src/OpenTelemetry.Exporter.Console/README.md)
|
||||
and
|
||||
[OpenTelemetry.Extensions.Hosting](../../../src/OpenTelemetry.Extensions.Hosting/README.md)
|
||||
packages:
|
||||
|
||||
```sh
|
||||
dotnet add package OpenTelemetry.Exporter.Console
|
||||
dotnet add package OpenTelemetry.Extensions.Hosting
|
||||
```
|
||||
|
||||
Update the `Program.cs` file with the code from [Program.cs](./Program.cs).
|
||||
|
||||
Run the application (using `dotnet run`) and then browse to the URL shown in the
|
||||
console for your application (e.g. `http://localhost:5000`). You should see the
|
||||
logs output from the console:
|
||||
|
||||
```text
|
||||
LogRecord.Timestamp: 2023-09-06T22:59:17.9787564Z
|
||||
LogRecord.CategoryName: getting-started-aspnetcore
|
||||
LogRecord.Severity: Info
|
||||
LogRecord.SeverityText: Information
|
||||
LogRecord.Body: Starting the app...
|
||||
LogRecord.Attributes (Key:Value):
|
||||
OriginalFormat (a.k.a Body): Starting the app...
|
||||
LogRecord.EventId: 1
|
||||
LogRecord.EventName: StartingApp
|
||||
|
||||
...
|
||||
|
||||
LogRecord.Timestamp: 2023-09-06T22:59:18.0644378Z
|
||||
LogRecord.CategoryName: Microsoft.Hosting.Lifetime
|
||||
LogRecord.Severity: Info
|
||||
LogRecord.SeverityText: Information
|
||||
LogRecord.Body: Now listening on: {address}
|
||||
LogRecord.Attributes (Key:Value):
|
||||
address: http://localhost:5000
|
||||
OriginalFormat (a.k.a Body): Now listening on: {address}
|
||||
LogRecord.EventId: 14
|
||||
LogRecord.EventName: ListeningOnAddress
|
||||
|
||||
...
|
||||
|
||||
LogRecord.Timestamp: 2023-09-06T23:00:46.1639248Z
|
||||
LogRecord.TraceId: 3507087d60ae4b1d2f10e68f4e40784a
|
||||
LogRecord.SpanId: c51be9f19c598b69
|
||||
LogRecord.TraceFlags: None
|
||||
LogRecord.CategoryName: Program
|
||||
LogRecord.Severity: Info
|
||||
LogRecord.SeverityText: Information
|
||||
LogRecord.Body: Food `{name}` price changed to `{price}`.
|
||||
LogRecord.Attributes (Key:Value):
|
||||
name: artichoke
|
||||
price: 9.99
|
||||
OriginalFormat (a.k.a Body): Food `{name}` price changed to `{price}`.
|
||||
LogRecord.EventId: 2
|
||||
LogRecord.EventName: FoodPriceChanged
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
Congratulations! You are now collecting logs using OpenTelemetry.
|
||||
|
||||
What does the above program do?
|
||||
|
||||
The program has cleared the default [logging
|
||||
providers](https://learn.microsoft.com/dotnet/core/extensions/logging-providers)
|
||||
then added OpenTelemetry as a logging provider to the ASP.NET Core logging
|
||||
pipeline. OpenTelemetry SDK is then configured with a
|
||||
[ConsoleExporter](../../../src/OpenTelemetry.Exporter.Console/README.md) to
|
||||
export the logs to the console for demonstration purpose (note: ConsoleExporter
|
||||
is not intended for production usage, other exporters such as [OTLP
|
||||
Exporter](../../../src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md)
|
||||
should be used instead). In addition, `OpenTelemetryLoggerOptions.IncludeScopes`
|
||||
is enabled so the logs will include the [log
|
||||
scopes](https://learn.microsoft.com/dotnet/core/extensions/logging#log-scopes).
|
||||
From the console output we can see the log scopes that are coming from the
|
||||
ASP.NET Core framework, and we can see logs from both our logger and the ASP.NET
|
||||
Core framework loggers, as indicated by the `LogRecord.CategoryName`.
|
||||
|
||||
The example has demonstrated the best practice from ASP.NET Core by injecting
|
||||
generic `ILogger<T>`:
|
||||
|
||||
```csharp
|
||||
app.MapGet("/", (ILogger<Program> logger) =>
|
||||
{
|
||||
logger.FoodPriceChanged("artichoke", 9.99);
|
||||
|
||||
return "Hello from OpenTelemetry Logs!";
|
||||
});
|
||||
```
|
||||
|
||||
Following the .NET logging best practice, [compile-time logging source
|
||||
generation](https://docs.microsoft.com/dotnet/core/extensions/logger-message-generator)
|
||||
has been used across the example, which delivers high performance, structured
|
||||
logging, and type-checked parameters:
|
||||
|
||||
```csharp
|
||||
public static partial class ApplicationLogs
|
||||
{
|
||||
[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Starting the app...")]
|
||||
public static partial void StartingApp(this ILogger logger);
|
||||
|
||||
[LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "Food `{name}` price changed to `{price}`.")]
|
||||
public static partial void FoodPriceChanged(this ILogger logger, string name, double price);
|
||||
}
|
||||
```
|
||||
|
||||
For logs that occur between `builder.Build()` and `app.Run()` when injecting a
|
||||
generic `ILogger<T>` is not an option, `app.Logger` is used instead:
|
||||
|
||||
```csharp
|
||||
app.Logger.StartingApp();
|
||||
```
|
||||
|
||||
## Learn more
|
||||
|
||||
* [Compile-time logging source
|
||||
generation](https://docs.microsoft.com/dotnet/core/extensions/logger-message-generator)
|
||||
* [Customizing the OpenTelemetry .NET SDK](../customizing-the-sdk/README.md)
|
||||
* [Extending the OpenTelemetry .NET SDK](../extending-the-sdk/README.md)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loading…
Reference in New Issue