Skip to content
This repository was archived by the owner on Apr 11, 2024. It is now read-only.

Commit eb751de

Browse files
committed
feat(enrolling): add open telemetry integration
OpenTelemetry beta is released. As an early adopter, I am integrating it with enrolling service first. I am also creating the first meta package of eSchool project for the integration. This package is consumed by using project reference rather NuGet package as this is a monorepo. This meta package has some extension methods which I will move to separate project once consolidated.
1 parent a03d284 commit eb751de

18 files changed

Lines changed: 259 additions & 7 deletions

File tree

deploy/k8s/charts/enrolling/templates/deployment.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ spec:
3838
value: {{ .Values.istio.prefix }}
3939
- name: ConnectionStrings
4040
value: {{ .Values.database.sql.connectionString | quote }}
41+
- name: OpenTelemetry__Istio
42+
value: "true"
43+
- name: OpenTelemetry__Jaeger__Host
44+
value: {{ .Values.jaeger.host }}
4145
ports:
4246
- name: http
4347
containerPort: 80

deploy/k8s/charts/enrolling/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ istio:
6060
prefix: /enrolling-api
6161
hosts:
6262
- host: "*"
63+
jaeger:
64+
host: jaeger-agent.istio-system.svc.cluster.local
6365

6466
database:
6567
sql:

deploy/k8s/charts/setup.bat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kubectl create ns eschool
2+
kubectl label namespace eschool istio-injection=enabled
3+
kubectl -n eschool apply -f .\eschool-gateway.yaml
4+
helm -n eschool install mssql .\mssql\
5+
helm -n eschool install enrolling .\enrolling\

docker-compose.override.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,16 @@ services:
4242
- HealthChecksUI__HealthChecks__1__Uri=http://joining.api/hc
4343
ports:
4444
- "5107:80"
45+
46+
jaeger:
47+
environment:
48+
- COLLECTOR_ZIPKIN_HTTP_PORT=9411
49+
ports:
50+
- 5775:5775/udp
51+
- 6831:6831/udp
52+
- 6832:6832/udp
53+
- 5778:5778
54+
- 16686:16686
55+
- 14268:14268
56+
- 14250:14250
57+
- 9411:9411

docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ services:
2828
build:
2929
context: .
3030
dockerfile: src/Web/WebStatus/Dockerfile
31+
32+
jaeger:
33+
image: jaegertracing/all-in-one

eSchool.sln

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Joining.UnitTests", "src\Se
4040
EndProject
4141
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Joining.API", "src\Services\Joining\Joining.API\Joining.API.csproj", "{60198F92-1838-4524-BCC5-BA8946305A2C}"
4242
EndProject
43+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{74511F4E-FF9D-42C4-9531-A75C61270B73}"
44+
EndProject
45+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry", "src\Libraries\OpenTelemetry\OpenTelemetry.csproj", "{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}"
46+
EndProject
4347
Global
4448
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4549
Debug|Any CPU = Debug|Any CPU
@@ -194,6 +198,18 @@ Global
194198
{60198F92-1838-4524-BCC5-BA8946305A2C}.Release|x64.Build.0 = Release|Any CPU
195199
{60198F92-1838-4524-BCC5-BA8946305A2C}.Release|x86.ActiveCfg = Release|Any CPU
196200
{60198F92-1838-4524-BCC5-BA8946305A2C}.Release|x86.Build.0 = Release|Any CPU
201+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
202+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
203+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|x64.ActiveCfg = Debug|Any CPU
204+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|x64.Build.0 = Debug|Any CPU
205+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|x86.ActiveCfg = Debug|Any CPU
206+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|x86.Build.0 = Debug|Any CPU
207+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
208+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|Any CPU.Build.0 = Release|Any CPU
209+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|x64.ActiveCfg = Release|Any CPU
210+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|x64.Build.0 = Release|Any CPU
211+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|x86.ActiveCfg = Release|Any CPU
212+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|x86.Build.0 = Release|Any CPU
197213
EndGlobalSection
198214
GlobalSection(SolutionProperties) = preSolution
199215
HideSolutionNode = FALSE
@@ -214,6 +230,8 @@ Global
214230
{46F2E473-A24A-44F7-973B-EB203A59FF00} = {8D2EFB6A-917E-4B93-890B-EBDD71476716}
215231
{039410B3-0844-4AE2-B0D3-3D2EC8AA8D6E} = {8D2EFB6A-917E-4B93-890B-EBDD71476716}
216232
{60198F92-1838-4524-BCC5-BA8946305A2C} = {8D2EFB6A-917E-4B93-890B-EBDD71476716}
233+
{74511F4E-FF9D-42C4-9531-A75C61270B73} = {6BFF1AB8-C900-43E5-988F-E07C085BD64A}
234+
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5} = {74511F4E-FF9D-42C4-9531-A75C61270B73}
217235
EndGlobalSection
218236
GlobalSection(ExtensibilityGlobals) = postSolution
219237
SolutionGuid = {E418719F-3193-403E-AF58-9BE9F94FD8BE}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System;
2+
using Microsoft.Extensions.Configuration;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using OpenTelemetry.Context.Propagation;
5+
using OpenTelemetry.Trace;
6+
using OpenTelemetry.Trace.Samplers;
7+
8+
namespace OpenCodeFoundation.OpenTelemetry
9+
{
10+
public static class Extensions
11+
{
12+
private const string SectionName = "OpenTelemetry";
13+
14+
public static IServiceCollection AddOpenTelemetryIntegration(
15+
this IServiceCollection services,
16+
Action<OpenTelemetryOptions> options = null,
17+
string sectionName = SectionName)
18+
{
19+
var openTelemetryOptions = services.GetOptions(sectionName, options);
20+
21+
if (openTelemetryOptions.Enabled)
22+
{
23+
ConfigureOpenTelemetry(services, openTelemetryOptions);
24+
}
25+
26+
return services;
27+
}
28+
29+
public static T GetOptions<T>(
30+
this IServiceCollection services,
31+
string sectionName,
32+
Action<T> configure = null)
33+
where T : IConfigurationOptions, new()
34+
{
35+
var provider = services.BuildServiceProvider();
36+
var configuration = provider.GetRequiredService<IConfiguration>();
37+
38+
var options = new T();
39+
configure?.Invoke(options);
40+
41+
configuration.GetSection(sectionName).Bind(options);
42+
43+
options.Validate();
44+
return options;
45+
}
46+
47+
private static void ConfigureOpenTelemetry(IServiceCollection services, OpenTelemetryOptions openTelemetryOptions)
48+
{
49+
services.AddOpenTelemetry(configure =>
50+
{
51+
ConfigureSampler(openTelemetryOptions, configure);
52+
ConfigureInstrumentations(openTelemetryOptions, configure);
53+
ConfigureExporters(openTelemetryOptions, configure);
54+
});
55+
}
56+
57+
private static void ConfigureSampler(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
58+
{
59+
if (openTelemetryOptions.AlwaysOnSampler)
60+
{
61+
configure.SetSampler(new AlwaysOnSampler());
62+
}
63+
}
64+
65+
private static void ConfigureExporters(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
66+
{
67+
if (openTelemetryOptions.Jaeger.Enabled)
68+
{
69+
configure.UseJaegerExporter(config =>
70+
{
71+
config.ServiceName = openTelemetryOptions.Jaeger.ServiceName;
72+
73+
config.AgentHost = openTelemetryOptions.Jaeger.Host;
74+
config.AgentPort = openTelemetryOptions.Jaeger.Port;
75+
});
76+
}
77+
}
78+
79+
private static void ConfigureInstrumentations(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
80+
{
81+
configure.AddAspNetCoreInstrumentation(config =>
82+
{
83+
config.TextFormat = GetTextFormat(openTelemetryOptions);
84+
});
85+
86+
configure.AddHttpClientInstrumentation(config =>
87+
{
88+
config.TextFormat = GetTextFormat(openTelemetryOptions);
89+
});
90+
91+
configure.AddSqlClientDependencyInstrumentation();
92+
}
93+
94+
private static ITextFormat GetTextFormat(OpenTelemetryOptions openTelemetryOptions)
95+
=> openTelemetryOptions.Istio
96+
? new B3Format()
97+
: (ITextFormat)new TraceContextFormat();
98+
}
99+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace OpenCodeFoundation.OpenTelemetry
2+
{
3+
public interface IConfigurationOptions
4+
{
5+
public void Validate();
6+
}
7+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net5.0</TargetFramework>
5+
<AssemblyName>OpenCodeFoundation.OpenTelemetry</AssemblyName>
6+
<RootNamespace>OpenCodeFoundation.OpenTelemetry</RootNamespace>
7+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
8+
9+
<CodeAnalysisRuleSet>..\..\..\eSchool.ruleset</CodeAnalysisRuleSet>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<!-- Asp.net required packages -->
14+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.7.20364.11" />
15+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.7.20364.11" />
16+
17+
<!-- OpenTelemetry -->
18+
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="0.4.0-beta.2" />
19+
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="0.4.0-beta.2" />
20+
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="0.4.0-beta.2" />
21+
<PackageReference Include="OpenTelemetry.Instrumentation.SqlClient" Version="0.4.0-beta.2" />
22+
<PackageReference Include="OpenTelemetry.Exporter.Jaeger" Version="0.4.0-beta.2" />
23+
<!-- <PackageReference Include="OpenTelemetry.Instrumentation.StackExchangeRedis" Version="0.4.0-beta.2" /> -->
24+
25+
<!-- Analyzers -->
26+
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
27+
28+
</ItemGroup>
29+
30+
<ItemGroup>
31+
<AdditionalFiles Include="..\..\stylecop.json" />
32+
</ItemGroup>
33+
34+
</Project>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
3+
namespace OpenCodeFoundation.OpenTelemetry
4+
{
5+
public class OpenTelemetryOptions
6+
: IConfigurationOptions
7+
{
8+
public bool Enabled { get; set; } = false;
9+
10+
public bool AlwaysOnSampler { get; set; } = true;
11+
12+
public bool Istio { get; set; } = false;
13+
14+
public JaegerOptions Jaeger { get; set; } = new JaegerOptions();
15+
16+
public void Validate()
17+
{
18+
if (Jaeger.Enabled)
19+
{
20+
ValidateJaeger();
21+
}
22+
}
23+
24+
private void ValidateJaeger()
25+
{
26+
if (string.IsNullOrWhiteSpace(Jaeger.ServiceName))
27+
{
28+
throw new ArgumentException("Jaeger service name can not be null if Jaeger is enabled");
29+
}
30+
31+
if (string.IsNullOrWhiteSpace(Jaeger.Host))
32+
{
33+
throw new ArgumentException("Jaeger Host can not be null if Jaeger is enabled");
34+
}
35+
}
36+
}
37+
38+
public class JaegerOptions
39+
{
40+
public bool Enabled { get; set; } = false;
41+
42+
public string ServiceName { get; set; }
43+
44+
public string Host { get; set; }
45+
46+
public int Port { get; set; }
47+
}
48+
}

0 commit comments

Comments
 (0)