Skip to content

Commit

Permalink
Merge branch 'main' into feat/exception-endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
alanwest authored Jan 27, 2024
2 parents ab846dc + 3fb2ec5 commit e9a836b
Show file tree
Hide file tree
Showing 53 changed files with 1,034 additions and 309 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/Component.BuildTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
run: dotnet-coverage merge -r -f cobertura -o ./TestResults/Cobertura.xml ./TestResults/*.coverage

- name: Upload code coverage ${{ inputs.code-cov-prefix }}-${{ inputs.code-cov-name }}
uses: codecov/codecov-action@v3.1.4
uses: codecov/codecov-action@v3.1.5
continue-on-error: true # Note: Don't fail for upload failures
env:
OS: ${{ matrix.os }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ jobs:
needs: detect-changes
if: |
contains(needs.detect-changes.outputs.changes, 'packaged-code')
|| contains(needs.detect-changes.outputs.changes, 'md')
|| contains(needs.detect-changes.outputs.changes, 'build')
|| contains(needs.detect-changes.outputs.changes, 'shared')
uses: ./.github/workflows/docfx.yml
Expand Down
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
<PackageVersion Include="Grpc.AspNetCore.Server" Version="[2.59.0, 3.0)" />
<PackageVersion Include="Grpc.Tools" Version="[2.59.0,3.0)" />
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="[3.11.0-beta1.23525.2]" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.1.2" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.1.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="[8.0.0,)" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="[8.0.0,)" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="[8.0.0,)" />
Expand Down
19 changes: 16 additions & 3 deletions OpenTelemetry.sln
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.github\workflows\ci-concurrency.yml = .github\workflows\ci-concurrency.yml
CONTRIBUTING.md = CONTRIBUTING.md
global.json = global.json
NuGet.config = NuGet.config
LICENSE.TXT = LICENSE.TXT
NuGet.config = NuGet.config
OpenTelemetry.proj = OpenTelemetry.proj
README.md = README.md
VERSIONING.md = VERSIONING.md
THIRD-PARTY-NOTICES.TXT = THIRD-PARTY-NOTICES.TXT
VERSIONING.md = VERSIONING.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7CB2F02E-03FA-4FFF-89A5-C51F107623FD}"
Expand Down Expand Up @@ -154,7 +154,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "metrics", "metrics", "{3277
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "logs", "logs", "{3862190B-E2C5-418E-AFDC-DB281FB5C705}"
ProjectSection(SolutionItems) = preProject
docs\logs\getting-started-console\README.md = docs\logs\getting-started-console\README.md
docs\logs\README.md = docs\logs\README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MicroserviceExample", "MicroserviceExample", "{4D492D62-5150-45F9-817F-C99562E364E2}"
Expand Down Expand Up @@ -333,6 +333,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "experimental-apis", "experi
docs\diagnostics\experimental-apis\README.md = docs\diagnostics\experimental-apis\README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "resources", "resources", "{A115CE4C-71A8-4B95-96A5-C1DF46FD94C2}"
ProjectSection(SolutionItems) = preProject
docs\resources\README.md = docs\resources\README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "extending-the-sdk", "docs\resources\extending-the-sdk\extending-the-sdk.csproj", "{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -615,6 +622,10 @@ Global
{B4856711-6D4C-4246-A686-49458D4C1301}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4856711-6D4C-4246-A686-49458D4C1301}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4856711-6D4C-4246-A686-49458D4C1301}.Release|Any CPU.Build.0 = Release|Any CPU
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -667,6 +678,8 @@ Global
{B4856711-6D4C-4246-A686-49458D4C1301} = {5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}
{52AF6D7D-9E66-4234-9A2C-5D16C6F22B40} = {7C87CAF9-79D7-4C26-9FFB-F3F1FB6911F1}
{17A22B0E-6EC3-4A39-B955-0A486AD06699} = {52AF6D7D-9E66-4234-9A2C-5D16C6F22B40}
{A115CE4C-71A8-4B95-96A5-C1DF46FD94C2} = {7C87CAF9-79D7-4C26-9FFB-F3F1FB6911F1}
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE} = {A115CE4C-71A8-4B95-96A5-C1DF46FD94C2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521}
Expand Down
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ doc](https://docs.google.com/document/d/1yjjD6aBcLxlRazYrawukDgrhZMObwHARJbB9glW
If you have trouble accessing the doc, please get in touch on
[Slack](https://cloud-native.slack.com/archives/C01N3BC2W7Q).

The meeting is open for all to join. We invite everyone to join our meeting,
regardless of your experience level. Whether you're a seasoned OpenTelemetry
developer, just starting your journey, or simply curious about the work we do,
you're more than welcome to participate!

[Maintainers](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer)
([@open-telemetry/dotnet-maintainers](https://github.com/orgs/open-telemetry/teams/dotnet-maintainers)):

Expand Down Expand Up @@ -149,20 +154,21 @@ Maintainer/Approver/Triager](https://github.com/open-telemetry/community/blob/ma

## Release Schedule

Only the [core components](./VERSIONING.md#core-components) of the repo have
released a stable version. Components which are marked
[pre-release](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#pre-releases),
are still work in progress and can undergo many breaking changes before stable
release.
See the [project
milestones](https://github.com/open-telemetry/opentelemetry-dotnet/milestones)
for details on upcoming releases. The dates and features described in issues and
milestones are estimates, and subject to change.

See the [release
notes](https://github.com/open-telemetry/opentelemetry-dotnet/releases) for
existing releases.

See the [project
milestones](https://github.com/open-telemetry/opentelemetry-dotnet/milestones)
for details on upcoming releases. The dates and features described in issues and
milestones are estimates, and subject to change.
> [!CAUTION]
> Certain components, marked as
[pre-release](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#pre-releases),
are still work in progress and can undergo breaking changes before stable
release. Check the individual `README.md` file for each component to understand its
current state.

Daily builds from this repo are published to MyGet, and can be installed from
[this source](https://www.myget.org/F/opentelemetry/api/v3/index.json).
2 changes: 1 addition & 1 deletion docs/diagnostics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ to specific code patterns identified through static analysis.

## Experimental APIs

Range: OTEL1XXX
Range: OTEL1000 - OTEL1999

Experimental APIs exposed in OpenTelemetry .NET pre-relase builds. APIs are
exposed experimentally when either the OpenTelemetry Specification has
Expand Down
1 change: 1 addition & 0 deletions docs/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"files": [
".editorconfig",
"**.cs",
"Directory.Packages.props",
"LICENSE.TXT",
"THIRD-PARTY-NOTICES.TXT"
]
Expand Down
175 changes: 175 additions & 0 deletions docs/logs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# OpenTelemetry .NET Logs

## Best Practices

The following tutorials have demonstrated the best practices for logging with
OpenTelemetry .NET:

* [Getting Started - Console Application](./getting-started-console/README.md)
* [Getting Started - ASP.NET Core
Application](./getting-started-aspnetcore/README.md)
* [Logging with Complex Objects](./complex-objects/README.md)

## Structured Logging

:heavy_check_mark: You should use structured logging.

* Structured logging is more efficient than unstructured logging.
* Filtering and redaction can happen on invidual key-value pairs instead of
the entire log message.
* Storage and indexing are more efficient.
* Structured logging makes it easier to manage and consume logs.

:stop_sign: You should avoid string interpolation.

> [!WARNING]
> The following code has bad performance due to [string
interpolation](https://learn.microsoft.com/dotnet/csharp/tutorials/string-interpolation):

```csharp
var food = "tomato";
var price = 2.99;

logger.LogInformation($"Hello from {food} {price}.");
```

Refer to the [logging performance
benchmark](../../test/Benchmarks/Logs/LogBenchmarks.cs) for more details.

## Package Version

:heavy_check_mark: You should always use the
[`ILogger`](https://docs.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger)
interface (including
[`ILogger<TCategoryName>`](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger-1))
from the latest stable version of
[Microsoft.Extensions.Logging](https://www.nuget.org/packages/Microsoft.Extensions.Logging/)
package, regardless of the .NET runtime version being used:

* If you're using the latest stable version of [OpenTelemetry .NET
SDK](../../src/OpenTelemetry/README.md), you don't have to worry about the
version of `Microsoft.Extensions.Logging` package because it is already taken
care of for you via [package dependency](../../Directory.Packages.props).
* Starting from version `3.1.0`, the .NET runtime team is holding a high bar for
backward compatibility on `Microsoft.Extensions.Logging` even during major
version bumps, so compatibility is not a concern here.

## Logging API

:heavy_check_mark: You should use [compile-time logging source
generation](https://docs.microsoft.com/dotnet/core/extensions/logger-message-generator)
pattern to achieve the best performance.

```csharp
public static partial class Food
{
[LoggerMessage(Level = LogLevel.Information, Message = "Hello from {food} {price}.")]
public static partial void SayHello(ILogger logger, string food, double price);
}

var food = "tomato";
var price = 2.99;

Food.SayHello(logger, food, price);
```

> [!NOTE]
> There is no need to pass in an explicit
[EventId](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.eventid)
while using
[LoggerMessageAttribute](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.loggermessageattribute).
A durable `EventId` will be automatically assigned based on the hash of the
method name during code generation.

:heavy_check_mark: You can use
[LogPropertiesAttribute](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.logpropertiesattribute)
from
[Microsoft.Extensions.Telemetry.Abstractions](https://www.nuget.org/packages/Microsoft.Extensions.Telemetry.Abstractions/)
if you need to log complex objects. Check out the [Logging with Complex
Objects](./complex-objects/README.md) tutorial for more details.

:stop_sign: You should avoid the extension methods from
[LoggerExtensions](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.loggerextensions),
these methods are not optimized for performance.

> [!WARNING]
> The following code has bad performance due to
[boxing](https://learn.microsoft.com/dotnet/csharp/programming-guide/types/boxing-and-unboxing):

```csharp
var food = "tomato";
var price = 2.99;

logger.LogInformation("Hello from {food} {price}.", food, price);
```

Refer to the [logging performance
benchmark](../../test/Benchmarks/Logs/LogBenchmarks.cs) for more details.

## Logger Management

In order to use
[`ILogger`](https://docs.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger)
interface (including
[`ILogger<TCategoryName>`](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger-1)),
you need to first get a logger. How to get a logger depends on two things:

* The type of application you are building.
* The place where you want to log.

Here is the rule of thumb:

* If you are building an application with [dependency injection
(DI)](https://learn.microsoft.com/dotnet/core/extensions/dependency-injection)
(e.g. [ASP.NET Core](https://learn.microsoft.com/aspnet/core) and [.NET
Worker](https://learn.microsoft.com/dotnet/core/extensions/workers)), in most
cases you should use the logger provided by DI, there are special cases when
you want log before DI logging pipeline is available or after DI logging
pipeline is disposed. Refer to the [.NET official
document](https://learn.microsoft.com/dotnet/core/extensions/logging#integration-with-hosts-and-dependency-injection)
and [Getting Started with OpenTelemetry .NET Logs in 5 Minutes - ASP.NET Core
Application](./getting-started-aspnetcore/README.md) tutorial to learn more.
* If you are building an application without DI, create a `LoggerFactory`
instance and configure OpenTelemetry to work with it. Refer to the [Getting
Started with OpenTelemetry .NET Logs in 5 Minutes - Console
Application](./getting-started-console/README.md) tutorial to learn more.

:stop_sign: You should avoid creating `LoggerFactory` instances too frequently,
`LoggerFactory` is fairly expensive and meant to be reused throughout the
application. For most applications, one `LoggerFactory` instance per process
would be sufficient.

:heavy_check_mark: You should properly manage the lifecycle of
[LoggerFactory](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.loggerfactory)
instances if they are created by you.

* If you forget to dispose the `LoggerFactory` instance before the application
ends, logs might get dropped due to the lack of proper flush.
* If you dispose the `LoggerFactory` instance too early, any subsequent logging
API invocation associated with the logger factory could become no-op (i.e. no
logs will be emitted).

:heavy_check_mark: You should use the fully qualified class name as the log
category name. Refer to the [.NET official
document](https://learn.microsoft.com/dotnet/core/extensions/logging#log-category)
to learn more.

## Log Correlation

In OpenTelemetry, logs are automatically correlated to traces. Check the [Log
Correlation](./correlation/README.md) tutorial to learn more.

## Log Enrichment

TBD

## Log Filtering

Check the [Customizing OpenTelemetry .NET SDK for
Logs](./customizing-the-sdk/README.md#log-filtering) document to learn more.

## Log Redaction

Logs might contain sensitive information such as passwords and credit card
numbers, proper redaction is required to prevent privacy and security incidents.
Check the [Log Redaction](./redaction/README.md) tutorial to learn more.
10 changes: 10 additions & 0 deletions docs/logs/correlation/LoggerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using Microsoft.Extensions.Logging;

internal static partial class LoggerExtensions
{
[LoggerMessage(LogLevel.Information, "Food `{name}` price changed to `{price}`.")]
public static partial void FoodPriceChanged(this ILogger logger, string name, double price);
}
39 changes: 19 additions & 20 deletions docs/logs/correlation/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,39 @@
using OpenTelemetry.Logs;
using OpenTelemetry.Trace;

namespace Correlation;

public class Program
{
private static readonly ActivitySource MyActivitySource = new(
"MyCompany.MyProduct.MyLibrary");
private static readonly ActivitySource MyActivitySource = new("MyCompany.MyProduct.MyLibrary");

public static void Main()
{
// Setup Logging
using var loggerFactory = LoggerFactory.Create(builder =>
var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("MyCompany.MyProduct.MyLibrary")
.AddConsoleExporter()
.Build();

var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(options =>
builder.AddOpenTelemetry(logging =>
{
options.AddConsoleExporter();
logging.AddConsoleExporter();
});
});

var logger = loggerFactory.CreateLogger<Program>();

// Setup Traces
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("MyCompany.MyProduct.MyLibrary")
.AddConsoleExporter()
.Build();

// Emit activity
using (var activity = MyActivitySource.StartActivity("SayHello"))
{
activity?.SetTag("foo", 1);

// emit logs within the context
// of activity
logger.LogInformation("Hello from {name} {price}.", "tomato", 2.99);
// Write a log within the context of an activity
logger.FoodPriceChanged("artichoke", 9.99);
}

// Dispose logger factory before the application ends.
// This will flush the remaining logs and shutdown the logging pipeline.
loggerFactory.Dispose();

// Dispose tracer provider before the application ends.
// This will flush the remaining spans and shutdown the tracing pipeline.
tracerProvider.Dispose();
}
}
Loading

0 comments on commit e9a836b

Please sign in to comment.