Skip to content

Commit 948fa0f

Browse files
authored
Merge pull request #135 from serilog/dev
2.0.0 Release
2 parents 2eb8d4d + 003fcc2 commit 948fa0f

24 files changed

+465
-223
lines changed

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ artifacts:
88
deploy:
99
- provider: NuGet
1010
api_key:
11-
secure: apW0n5l5wmFRm83lovuguQ72JsFl0ldKJ0/iedICWlp+mRQrzjIILbjiR9YyOt6F
11+
secure: sDnchSg4TZIOK7oIUI6BJwFPNENTOZrGNsroGO1hehLJSvlHpFmpTwiX8+bgPD+Q
1212
skip_symbols: true
1313
on:
1414
branch: /^(main|dev)$/

example/Example/Example.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="7.0.2" />
11+
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.0" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

example/Example/Program.cs

Lines changed: 65 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -14,101 +14,83 @@
1414

1515
// ReSharper disable ExplicitCallerInfoArgument
1616

17-
#nullable enable
18-
1917
using Serilog;
2018
using System.Diagnostics;
19+
using Serilog.Core;
2120
using Serilog.Sinks.OpenTelemetry;
2221

23-
namespace Example;
24-
25-
static class Program
26-
{
27-
static readonly Random Rand = new();
28-
29-
static void Main()
30-
{
31-
// create an ActivitySource (that is listened to) for creating an Activity
32-
// to test the trace and span ID enricher
33-
using var listener = new ActivityListener
34-
{
35-
ShouldListenTo = _ => true,
36-
Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData,
37-
};
38-
39-
ActivitySource.AddActivityListener(listener);
22+
// Without activity listeners present, trace and span ids are not collected.
23+
using var listener = new ActivityListener();
24+
listener.ShouldListenTo = _ => true;
25+
listener.Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData;
26+
ActivitySource.AddActivityListener(listener);
4027

41-
var source = new ActivitySource("test.example", "1.0.0");
28+
var source = new ActivitySource("test.example", "1.0.0");
4229

43-
// Create the loggers to send to gRPC and to HTTP.
44-
var grpcLogger = GetLogger(OtlpProtocol.Grpc);
45-
var httpLogger = GetLogger(OtlpProtocol.HttpProtobuf);
30+
using (var grpcLogger = CreateLogger(OtlpProtocol.Grpc))
31+
{
32+
using var activity = source.StartActivity("grpc-loop");
33+
SendLogs(grpcLogger, "grpc");
34+
}
4635

47-
using (source.StartActivity("grpc-loop"))
48-
{
49-
SendLogs(grpcLogger, "grpc");
50-
}
36+
using (var httpLogger = CreateLogger(OtlpProtocol.HttpProtobuf))
37+
{
38+
using var activity = source.StartActivity("http-loop");
39+
SendLogs(httpLogger, "http/protobuf");
40+
}
5141

52-
using (source.StartActivity("http-loop"))
53-
{
54-
SendLogs(httpLogger, "http/protobuf");
55-
}
42+
static void SendLogs(ILogger logger, string protocol)
43+
{
44+
var position = new { Latitude = Random.Shared.Next(-90, 91), Longitude = Random.Shared.Next(0, 361) };
45+
var elapsedMs = Random.Shared.Next(0, 101);
46+
var roll = Random.Shared.Next(0, 7);
5647

57-
Thread.Sleep(5000);
58-
}
48+
logger
49+
.ForContext("Elapsed", elapsedMs)
50+
.ForContext("Protocol", protocol)
51+
.Information("The position is {@Position}", position);
5952

60-
static void SendLogs(ILogger logger, string protocol)
53+
try
6154
{
62-
var position = new { Latitude = Rand.Next(-90, 91), Longitude = Rand.Next(0, 361) };
63-
var elapsedMs = Rand.Next(0, 101);
64-
var roll = Rand.Next(0, 7);
65-
66-
logger
67-
.ForContext("Elapsed", elapsedMs)
68-
.ForContext("Protocol", protocol)
69-
.Information("The position is {@Position}", position);
70-
71-
try
72-
{
73-
throw new Exception(protocol);
74-
}
75-
catch (Exception ex)
76-
{
77-
logger.ForContext("protocol", protocol).Error(ex, "Error on roll {Roll}", roll);
78-
}
55+
throw new Exception(protocol);
7956
}
80-
81-
static ILogger GetLogger(OtlpProtocol protocol)
57+
catch (Exception ex)
8258
{
83-
var endpoint = protocol == OtlpProtocol.HttpProtobuf ?
84-
"http://localhost:4318/v1/logs" :
85-
"http://localhost:4317";
86-
87-
return new LoggerConfiguration()
88-
.MinimumLevel.Information()
89-
.WriteTo.OpenTelemetry(options => {
90-
options.Endpoint = endpoint;
91-
options.Protocol = protocol;
92-
options.IncludedData =
93-
IncludedData.SpanIdField
94-
| IncludedData.TraceIdField
95-
| IncludedData.MessageTemplateTextAttribute
96-
| IncludedData.MessageTemplateMD5HashAttribute;
97-
options.ResourceAttributes = new Dictionary<string, object>
98-
{
99-
["service.name"] = "test-logging-service",
100-
["index"] = 10,
101-
["flag"] = true,
102-
["pi"] = 3.14
103-
};
104-
options.Headers = new Dictionary<string, string>
105-
{
106-
["Authorization"] = "Basic dXNlcjphYmMxMjM=", // user:abc123
107-
};
108-
options.BatchingOptions.BatchSizeLimit = 2;
109-
options.BatchingOptions.Period = TimeSpan.FromSeconds(2);
110-
options.BatchingOptions.QueueLimit = 10;
111-
})
112-
.CreateLogger();
59+
logger.ForContext("protocol", protocol).Error(ex, "Error on roll {Roll}", roll);
11360
}
11461
}
62+
63+
static Logger CreateLogger(OtlpProtocol protocol)
64+
{
65+
var endpoint = protocol == OtlpProtocol.HttpProtobuf ?
66+
"http://localhost:4318/v1/logs" :
67+
"http://localhost:4317";
68+
69+
return new LoggerConfiguration()
70+
.WriteTo.OpenTelemetry(options => {
71+
options.Endpoint = endpoint;
72+
options.Protocol = protocol;
73+
// Prevent tracing of outbound requests from the sink
74+
options.HttpMessageHandler = new SocketsHttpHandler { ActivityHeadersPropagator = null };
75+
options.IncludedData =
76+
IncludedData.SpanIdField
77+
| IncludedData.TraceIdField
78+
| IncludedData.MessageTemplateTextAttribute
79+
| IncludedData.MessageTemplateMD5HashAttribute;
80+
options.ResourceAttributes = new Dictionary<string, object>
81+
{
82+
["service.name"] = "test-logging-service",
83+
["index"] = 10,
84+
["flag"] = true,
85+
["pi"] = 3.14
86+
};
87+
options.Headers = new Dictionary<string, string>
88+
{
89+
["Authorization"] = "Basic dXNlcjphYmMxMjM=", // user:abc123
90+
};
91+
options.BatchingOptions.BatchSizeLimit = 700;
92+
options.BatchingOptions.Period = TimeSpan.FromSeconds(1);
93+
options.BatchingOptions.QueueLimit = 10;
94+
})
95+
.CreateLogger();
96+
}

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "7.0.102",
3+
"version": "8.0.100",
44
"allowPrerelease": false,
55
"rollForward": "latestFeature"
66
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright © Serilog Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
namespace Serilog.Collections;
16+
17+
static class EnumerableExtensions
18+
{
19+
public static void AddTo<T>(this IEnumerable<T> from, ICollection<T> to)
20+
{
21+
foreach (var item in from)
22+
{
23+
to.Add(item);
24+
}
25+
}
26+
}

src/Serilog.Sinks.OpenTelemetry/OpenTelemetryLoggerConfigurationExtensions.cs

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using System.Net.Http;
1516
using Serilog.Configuration;
1617
using Serilog.Sinks.OpenTelemetry;
18+
using Serilog.Sinks.OpenTelemetry.Exporters;
1719
using Serilog.Sinks.PeriodicBatching;
20+
using Serilog.Collections;
21+
using Serilog.Core;
22+
using Serilog.Events;
1823

1924
namespace Serilog;
2025

@@ -23,6 +28,13 @@ namespace Serilog;
2328
/// </summary>
2429
public static class OpenTelemetryLoggerConfigurationExtensions
2530
{
31+
static HttpMessageHandler? CreateDefaultHttpMessageHandler() =>
32+
#if FEATURE_SOCKETS_HTTP_HANDLER
33+
new SocketsHttpHandler { ActivityHeadersPropagator = null };
34+
#else
35+
null;
36+
#endif
37+
2638
/// <summary>
2739
/// Send log events to an OTLP exporter.
2840
/// </summary>
@@ -39,14 +51,17 @@ public static LoggerConfiguration OpenTelemetry(
3951
var options = new BatchedOpenTelemetrySinkOptions();
4052
configure(options);
4153

42-
var openTelemetrySink = new OpenTelemetrySink(
54+
var exporter = Exporter.Create(
4355
endpoint: options.Endpoint,
4456
protocol: options.Protocol,
57+
headers: new Dictionary<string, string>(options.Headers),
58+
httpMessageHandler: options.HttpMessageHandler ?? CreateDefaultHttpMessageHandler());
59+
60+
var openTelemetrySink = new OpenTelemetrySink(
61+
exporter: exporter,
4562
formatProvider: options.FormatProvider,
4663
resourceAttributes: new Dictionary<string, object>(options.ResourceAttributes),
47-
headers: new Dictionary<string, string>(options.Headers),
48-
includedData: options.IncludedData,
49-
httpMessageHandler: options.HttpMessageHandler);
64+
includedData: options.IncludedData);
5065

5166
var sink = new PeriodicBatchingSink(openTelemetrySink, options.BatchingOptions);
5267

@@ -65,18 +80,44 @@ public static LoggerConfiguration OpenTelemetry(
6580
/// <param name="protocol">
6681
/// The OTLP protocol to use.
6782
/// </param>
83+
/// <param name="headers">
84+
/// Headers to send with network requests.
85+
/// </param>
86+
/// <param name="resourceAttributes">
87+
/// A attributes of the resource attached to the logs generated by the sink. The values must be simple primitive
88+
/// values: integers, doubles, strings, or booleans. Other values will be silently ignored.
89+
/// </param>
90+
/// <param name="includedData">
91+
/// Which fields should be included in the log events generated by the sink.
92+
/// </param>
93+
/// <param name="restrictedToMinimumLevel">
94+
/// The minimum level for events passed through the sink. Ignored when <paramref name="levelSwitch"/> is specified.
95+
/// </param>
96+
/// <param name="levelSwitch">
97+
/// A switch allowing the pass-through minimum level to be changed at runtime.
98+
/// </param>
6899
/// <returns>Logger configuration, allowing configuration to continue.</returns>
69100
public static LoggerConfiguration OpenTelemetry(
70101
this LoggerSinkConfiguration loggerSinkConfiguration,
71102
string endpoint = OpenTelemetrySinkOptions.DefaultEndpoint,
72-
OtlpProtocol protocol = OpenTelemetrySinkOptions.DefaultProtocol)
103+
OtlpProtocol protocol = OpenTelemetrySinkOptions.DefaultProtocol,
104+
IDictionary<string, string>? headers = null,
105+
IDictionary<string, object>? resourceAttributes = null,
106+
IncludedData? includedData = null,
107+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
108+
LoggingLevelSwitch? levelSwitch = null)
73109
{
74110
if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration));
75111

76112
return loggerSinkConfiguration.OpenTelemetry(options =>
77113
{
78114
options.Endpoint = endpoint;
79115
options.Protocol = protocol;
116+
options.IncludedData = includedData ?? options.IncludedData;
117+
options.RestrictedToMinimumLevel = restrictedToMinimumLevel;
118+
options.LevelSwitch = levelSwitch;
119+
headers?.AddTo(options.Headers);
120+
resourceAttributes?.AddTo(options.ResourceAttributes);
80121
});
81122
}
82123

@@ -97,14 +138,17 @@ public static LoggerConfiguration OpenTelemetry(
97138

98139
configure(options);
99140

100-
var sink = new OpenTelemetrySink(
141+
var exporter = Exporter.Create(
101142
endpoint: options.Endpoint,
102143
protocol: options.Protocol,
144+
headers: new Dictionary<string, string>(options.Headers),
145+
httpMessageHandler: options.HttpMessageHandler ?? CreateDefaultHttpMessageHandler());
146+
147+
var sink = new OpenTelemetrySink(
148+
exporter: exporter,
103149
formatProvider: options.FormatProvider,
104150
resourceAttributes: new Dictionary<string, object>(options.ResourceAttributes),
105-
headers: new Dictionary<string, string>(options.Headers),
106-
includedData: options.IncludedData,
107-
httpMessageHandler: options.HttpMessageHandler);
151+
includedData: options.IncludedData);
108152

109153
return loggerAuditSinkConfiguration.Sink(sink, options.RestrictedToMinimumLevel, options.LevelSwitch);
110154
}
@@ -121,18 +165,34 @@ public static LoggerConfiguration OpenTelemetry(
121165
/// <param name="protocol">
122166
/// The OTLP protocol to use.
123167
/// </param>
168+
/// <param name="headers">
169+
/// Headers to send with network requests.
170+
/// </param>
171+
/// <param name="resourceAttributes">
172+
/// A attributes of the resource attached to the logs generated by the sink. The values must be simple primitive
173+
/// values: integers, doubles, strings, or booleans. Other values will be silently ignored.
174+
/// </param>
175+
/// <param name="includedData">
176+
/// Which fields should be included in the log events generated by the sink.
177+
/// </param>
124178
/// <returns>Logger configuration, allowing configuration to continue.</returns>
125179
public static LoggerConfiguration OpenTelemetry(
126180
this LoggerAuditSinkConfiguration loggerAuditSinkConfiguration,
127181
string endpoint = OpenTelemetrySinkOptions.DefaultEndpoint,
128-
OtlpProtocol protocol = OpenTelemetrySinkOptions.DefaultProtocol)
182+
OtlpProtocol protocol = OpenTelemetrySinkOptions.DefaultProtocol,
183+
IDictionary<string, string>? headers = null,
184+
IDictionary<string, object>? resourceAttributes = null,
185+
IncludedData? includedData = null)
129186
{
130187
if (loggerAuditSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerAuditSinkConfiguration));
131188

132189
return loggerAuditSinkConfiguration.OpenTelemetry(options =>
133190
{
134191
options.Endpoint = endpoint;
135192
options.Protocol = protocol;
193+
options.IncludedData = includedData ?? options.IncludedData;
194+
headers?.AddTo(options.Headers);
195+
resourceAttributes?.AddTo(options.ResourceAttributes);
136196
});
137197
}
138198
}

0 commit comments

Comments
 (0)