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

Commit

Permalink
feat(enrolling): add open telemetry integration
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ratanparai committed Jul 26, 2020
1 parent a03d284 commit eb751de
Show file tree
Hide file tree
Showing 18 changed files with 259 additions and 7 deletions.
4 changes: 4 additions & 0 deletions deploy/k8s/charts/enrolling/templates/deployment.yaml
Expand Up @@ -38,6 +38,10 @@ spec:
value: {{ .Values.istio.prefix }}
- name: ConnectionStrings
value: {{ .Values.database.sql.connectionString | quote }}
- name: OpenTelemetry__Istio
value: "true"
- name: OpenTelemetry__Jaeger__Host
value: {{ .Values.jaeger.host }}
ports:
- name: http
containerPort: 80
Expand Down
2 changes: 2 additions & 0 deletions deploy/k8s/charts/enrolling/values.yaml
Expand Up @@ -60,6 +60,8 @@ istio:
prefix: /enrolling-api
hosts:
- host: "*"
jaeger:
host: jaeger-agent.istio-system.svc.cluster.local

database:
sql:
Expand Down
5 changes: 5 additions & 0 deletions deploy/k8s/charts/setup.bat
@@ -0,0 +1,5 @@
kubectl create ns eschool
kubectl label namespace eschool istio-injection=enabled
kubectl -n eschool apply -f .\eschool-gateway.yaml
helm -n eschool install mssql .\mssql\
helm -n eschool install enrolling .\enrolling\
13 changes: 13 additions & 0 deletions docker-compose.override.yml
Expand Up @@ -42,3 +42,16 @@ services:
- HealthChecksUI__HealthChecks__1__Uri=http://joining.api/hc
ports:
- "5107:80"

jaeger:
environment:
- COLLECTOR_ZIPKIN_HTTP_PORT=9411
ports:
- 5775:5775/udp
- 6831:6831/udp
- 6832:6832/udp
- 5778:5778
- 16686:16686
- 14268:14268
- 14250:14250
- 9411:9411
3 changes: 3 additions & 0 deletions docker-compose.yml
Expand Up @@ -28,3 +28,6 @@ services:
build:
context: .
dockerfile: src/Web/WebStatus/Dockerfile

jaeger:
image: jaegertracing/all-in-one
18 changes: 18 additions & 0 deletions eSchool.sln
Expand Up @@ -40,6 +40,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Joining.UnitTests", "src\Se
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Joining.API", "src\Services\Joining\Joining.API\Joining.API.csproj", "{60198F92-1838-4524-BCC5-BA8946305A2C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{74511F4E-FF9D-42C4-9531-A75C61270B73}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry", "src\Libraries\OpenTelemetry\OpenTelemetry.csproj", "{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -194,6 +198,18 @@ Global
{60198F92-1838-4524-BCC5-BA8946305A2C}.Release|x64.Build.0 = Release|Any CPU
{60198F92-1838-4524-BCC5-BA8946305A2C}.Release|x86.ActiveCfg = Release|Any CPU
{60198F92-1838-4524-BCC5-BA8946305A2C}.Release|x86.Build.0 = Release|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|x64.ActiveCfg = Debug|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|x64.Build.0 = Debug|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|x86.ActiveCfg = Debug|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Debug|x86.Build.0 = Debug|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|Any CPU.Build.0 = Release|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|x64.ActiveCfg = Release|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|x64.Build.0 = Release|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|x86.ActiveCfg = Release|Any CPU
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -214,6 +230,8 @@ Global
{46F2E473-A24A-44F7-973B-EB203A59FF00} = {8D2EFB6A-917E-4B93-890B-EBDD71476716}
{039410B3-0844-4AE2-B0D3-3D2EC8AA8D6E} = {8D2EFB6A-917E-4B93-890B-EBDD71476716}
{60198F92-1838-4524-BCC5-BA8946305A2C} = {8D2EFB6A-917E-4B93-890B-EBDD71476716}
{74511F4E-FF9D-42C4-9531-A75C61270B73} = {6BFF1AB8-C900-43E5-988F-E07C085BD64A}
{7B410F3B-36E0-4853-9B4E-41D0CC2865B5} = {74511F4E-FF9D-42C4-9531-A75C61270B73}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E418719F-3193-403E-AF58-9BE9F94FD8BE}
Expand Down
99 changes: 99 additions & 0 deletions src/Libraries/OpenTelemetry/Extensions.cs
@@ -0,0 +1,99 @@
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Samplers;

namespace OpenCodeFoundation.OpenTelemetry
{
public static class Extensions
{
private const string SectionName = "OpenTelemetry";

public static IServiceCollection AddOpenTelemetryIntegration(
this IServiceCollection services,
Action<OpenTelemetryOptions> options = null,
string sectionName = SectionName)
{
var openTelemetryOptions = services.GetOptions(sectionName, options);

if (openTelemetryOptions.Enabled)
{
ConfigureOpenTelemetry(services, openTelemetryOptions);
}

return services;
}

public static T GetOptions<T>(
this IServiceCollection services,
string sectionName,
Action<T> configure = null)
where T : IConfigurationOptions, new()
{
var provider = services.BuildServiceProvider();
var configuration = provider.GetRequiredService<IConfiguration>();

var options = new T();
configure?.Invoke(options);

configuration.GetSection(sectionName).Bind(options);

options.Validate();
return options;
}

private static void ConfigureOpenTelemetry(IServiceCollection services, OpenTelemetryOptions openTelemetryOptions)
{
services.AddOpenTelemetry(configure =>
{
ConfigureSampler(openTelemetryOptions, configure);
ConfigureInstrumentations(openTelemetryOptions, configure);
ConfigureExporters(openTelemetryOptions, configure);
});
}

private static void ConfigureSampler(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
{
if (openTelemetryOptions.AlwaysOnSampler)
{
configure.SetSampler(new AlwaysOnSampler());
}
}

private static void ConfigureExporters(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
{
if (openTelemetryOptions.Jaeger.Enabled)
{
configure.UseJaegerExporter(config =>
{
config.ServiceName = openTelemetryOptions.Jaeger.ServiceName;
config.AgentHost = openTelemetryOptions.Jaeger.Host;
config.AgentPort = openTelemetryOptions.Jaeger.Port;
});
}
}

private static void ConfigureInstrumentations(OpenTelemetryOptions openTelemetryOptions, TracerProviderBuilder configure)
{
configure.AddAspNetCoreInstrumentation(config =>
{
config.TextFormat = GetTextFormat(openTelemetryOptions);
});

configure.AddHttpClientInstrumentation(config =>
{
config.TextFormat = GetTextFormat(openTelemetryOptions);
});

configure.AddSqlClientDependencyInstrumentation();
}

private static ITextFormat GetTextFormat(OpenTelemetryOptions openTelemetryOptions)
=> openTelemetryOptions.Istio
? new B3Format()
: (ITextFormat)new TraceContextFormat();
}
}
7 changes: 7 additions & 0 deletions src/Libraries/OpenTelemetry/IConfigurationOptions.cs
@@ -0,0 +1,7 @@
namespace OpenCodeFoundation.OpenTelemetry
{
public interface IConfigurationOptions
{
public void Validate();
}
}
34 changes: 34 additions & 0 deletions src/Libraries/OpenTelemetry/OpenTelemetry.csproj
@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>OpenCodeFoundation.OpenTelemetry</AssemblyName>
<RootNamespace>OpenCodeFoundation.OpenTelemetry</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

<CodeAnalysisRuleSet>..\..\..\eSchool.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>

<ItemGroup>
<!-- Asp.net required packages -->
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.7.20364.11" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.7.20364.11" />

<!-- OpenTelemetry -->
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="0.4.0-beta.2" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="0.4.0-beta.2" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="0.4.0-beta.2" />
<PackageReference Include="OpenTelemetry.Instrumentation.SqlClient" Version="0.4.0-beta.2" />
<PackageReference Include="OpenTelemetry.Exporter.Jaeger" Version="0.4.0-beta.2" />
<!-- <PackageReference Include="OpenTelemetry.Instrumentation.StackExchangeRedis" Version="0.4.0-beta.2" /> -->

<!-- Analyzers -->
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />

</ItemGroup>

<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json" />
</ItemGroup>

</Project>
48 changes: 48 additions & 0 deletions src/Libraries/OpenTelemetry/OpenTelemetryOptions.cs
@@ -0,0 +1,48 @@
using System;

namespace OpenCodeFoundation.OpenTelemetry
{
public class OpenTelemetryOptions
: IConfigurationOptions
{
public bool Enabled { get; set; } = false;

public bool AlwaysOnSampler { get; set; } = true;

public bool Istio { get; set; } = false;

public JaegerOptions Jaeger { get; set; } = new JaegerOptions();

public void Validate()
{
if (Jaeger.Enabled)
{
ValidateJaeger();
}
}

private void ValidateJaeger()
{
if (string.IsNullOrWhiteSpace(Jaeger.ServiceName))
{
throw new ArgumentException("Jaeger service name can not be null if Jaeger is enabled");
}

if (string.IsNullOrWhiteSpace(Jaeger.Host))
{
throw new ArgumentException("Jaeger Host can not be null if Jaeger is enabled");
}
}
}

public class JaegerOptions
{
public bool Enabled { get; set; } = false;

public string ServiceName { get; set; }

public string Host { get; set; }

public int Port { get; set; }
}
}
Expand Up @@ -10,7 +10,8 @@ public class LoggingBehavior<TRequest, TResponse>
{
private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;

public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
public LoggingBehavior(
ILogger<LoggingBehavior<TRequest, TResponse>> logger)
{
_logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
}
Expand Down
2 changes: 2 additions & 0 deletions src/Services/Enrolling/Enrolling.API/Dockerfile
Expand Up @@ -19,6 +19,8 @@ COPY "src/Services/Joining/Joining.Infrastructure/Joining.Infrastructure.csproj"
COPY "src/Services/Joining/Joining.UnitTests/Joining.UnitTests.csproj" "src/Services/Joining/Joining.UnitTests/Joining.UnitTests.csproj"
COPY "src/Services/Joining/Joining.FunctionalTests/Joining.FunctionalTests.csproj" "src/Services/Joining/Joining.FunctionalTests/Joining.FunctionalTests.csproj"

COPY "src/Libraries/OpenTelemetry/OpenTelemetry.csproj" "src/Libraries/OpenTelemetry/OpenTelemetry.csproj"

COPY "src/Web/WebStatus/WebStatus.csproj" "src/Web/WebStatus/WebStatus.csproj"

COPY "docker-compose.dcproj" "docker-compose.dcproj"
Expand Down
5 changes: 3 additions & 2 deletions src/Services/Enrolling/Enrolling.API/Enrolling.API.csproj
Expand Up @@ -28,14 +28,14 @@
<PackageReference Include="Polly" Version="7.2.1" />

<!-- Logging -->
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="4.0.0" />

<!-- Swagger -->
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />

<!-- Need this package for generating migration files -->
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0-preview.6.20312.4">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0-preview.7.20365.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Expand All @@ -52,6 +52,7 @@
<ItemGroup>
<ProjectReference Include="..\Enrolling.Infrastructure\Enrolling.Infrastructure.csproj" />
<ProjectReference Include="..\Enrolling.Domain\Enrolling.Domain.csproj" />
<ProjectReference Include="..\..\..\Libraries\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions src/Services/Enrolling/Enrolling.API/Startup.cs
Expand Up @@ -16,6 +16,7 @@
using OpenCodeFoundation.ESchool.Services.Enrolling.API.Application.Validations;
using OpenCodeFoundation.ESchool.Services.Enrolling.API.Extensions;
using OpenCodeFoundation.ESchool.Services.Enrolling.Infrastructure;
using OpenCodeFoundation.OpenTelemetry;

namespace OpenCodeFoundation.ESchool.Services.Enrolling.API
{
Expand Down Expand Up @@ -60,6 +61,8 @@ public void ConfigureServices(IServiceCollection services)
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Enrolling HTTP API", Version = "v1" });
});

services.AddOpenTelemetryIntegration();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand Down
12 changes: 11 additions & 1 deletion src/Services/Enrolling/Enrolling.API/appsettings.json
Expand Up @@ -10,5 +10,15 @@
}
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"OpenTelemetry": {
"Enabled": true,
"Istio": false,
"Jaeger": {
"Enabled": true,
"ServiceName": "enrolling.api",
"Host": "jaeger",
"Port": 6831
}
}
}
Expand Up @@ -10,7 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.0-preview.6.20312.15" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.0-preview.7.20365.19" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2" />
Expand Down
Expand Up @@ -15,8 +15,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.6.20312.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.6.20312.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.7.20365.15" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.7.20365.15" />

<!-- Analyzers -->
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
Expand Down
2 changes: 2 additions & 0 deletions src/Web/WebStatus/Dockerfile
Expand Up @@ -19,6 +19,8 @@ COPY "src/Services/Joining/Joining.Infrastructure/Joining.Infrastructure.csproj"
COPY "src/Services/Joining/Joining.UnitTests/Joining.UnitTests.csproj" "src/Services/Joining/Joining.UnitTests/Joining.UnitTests.csproj"
COPY "src/Services/Joining/Joining.FunctionalTests/Joining.FunctionalTests.csproj" "src/Services/Joining/Joining.FunctionalTests/Joining.FunctionalTests.csproj"

COPY "src/Libraries/OpenTelemetry/OpenTelemetry.csproj" "src/Libraries/OpenTelemetry/OpenTelemetry.csproj"

COPY "src/Web/WebStatus/WebStatus.csproj" "src/Web/WebStatus/WebStatus.csproj"

COPY "docker-compose.dcproj" "docker-compose.dcproj"
Expand Down

0 comments on commit eb751de

Please sign in to comment.