Skip to content

Commit 7a98fe1

Browse files
Improved tracing
1 parent dfcda3f commit 7a98fe1

File tree

17 files changed

+167
-143
lines changed

17 files changed

+167
-143
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<ImplicitUsings>enable</ImplicitUsings>
55
<Nullable>enable</Nullable>
66
<IsPackable>true</IsPackable>
7-
<Version>2.2.38</Version>
7+
<Version>2.2.43</Version>
88
<Authors>Andrey Serdyuk</Authors>
99
<Company>TaskHub</Company>
1010
<Title>TaskHub.Shared - Reusable Primitives for .NET Microservices</Title>

TaskHub.Observability.Logger.Serilog/LogService.cs

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,21 @@
44

55
namespace TaskHub.Observability.Logger.Serilog;
66

7-
public sealed class LogService(ILogger log, SerilogOptions options) : ILogService
7+
public sealed class LogService() : ILogService
88
{
9-
private readonly ILogger _log = log.ForContext<LogService>();
9+
private readonly ILogger _log = Log.ForContext<LogService>();
1010

11-
public void Debug(string message, object? data = null)
12-
{
13-
if (options.IsEnabled)
14-
{
15-
Write(LogEventLevel.Debug, message, null, data);
16-
}
17-
}
11+
public void Debug(string message, object? data = null) =>
12+
Write(LogEventLevel.Debug, message, null, data);
1813

19-
public void Info(string message, object? data = null)
20-
{
21-
if (options.IsEnabled)
22-
{
23-
Write(LogEventLevel.Information, message, null, data);
24-
}
25-
}
14+
public void Info(string message, object? data = null) =>
15+
Write(LogEventLevel.Information, message, null, data);
2616

27-
public void Warning(string message, object? data = null)
28-
{
29-
if (options.IsEnabled)
30-
{
31-
Write(LogEventLevel.Warning, message, null, data);
32-
}
33-
}
17+
public void Warning(string message, object? data = null) =>
18+
Write(LogEventLevel.Warning, message, null, data);
3419

35-
public void Error(string message, Exception? exception = null, object? data = null)
36-
{
37-
if (options.IsEnabled)
38-
{
39-
Write(LogEventLevel.Error, message, exception, data);
40-
}
41-
}
20+
public void Error(string message, Exception? exception = null, object? data = null) =>
21+
Write(LogEventLevel.Error, message, exception, data);
4222

4323
private void Write(LogEventLevel level, string message, Exception? exception, object? data)
4424
{
Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1-
using Microsoft.Extensions.Configuration;
2-
using Microsoft.Extensions.DependencyInjection;
3-
using Microsoft.Extensions.Logging;
1+
using Microsoft.AspNetCore.Builder;
42
using Serilog;
5-
using TaskHub.Observability.Logger.Abstractions;
63

74
namespace TaskHub.Observability.Logger.Serilog;
85

96
public static class SerilogBoostrap
107
{
11-
public static void AddAppSerilog(this IServiceCollection services, IConfiguration configuration)
8+
public static void AddAppSerilog(this ConfigureHostBuilder host, string serviceName)
129
{
13-
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).Enrich.FromLogContext().CreateLogger();
14-
15-
services.AddLogging(lb =>
16-
{
17-
lb.ClearProviders();
18-
lb.AddSerilog(Log.Logger, dispose: true);
19-
});
20-
21-
services.AddSingleton<ILogService>(new LogService(Log.Logger, configuration.GetSection("Loki").Get<SerilogOptions>() ?? new()));
10+
host.UseSerilog((ctx, lc) => lc.ReadFrom.Configuration(ctx.Configuration)
11+
.Enrich.FromLogContext()
12+
.Enrich.WithProperty("ServiceName", serviceName));
2213
}
2314
}

TaskHub.Observability.Traces.Abstractions/Service/ITracesService.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ namespace TaskHub.Observability.Traces.Abstractions.Service;
44

55
public interface ITracesService
66
{
7-
public Activity? Current { get; }
8-
public Activity? StartParent(string name);
9-
public Activity? StartParent(string name, ActivityKind kind);
10-
public Activity? StartChild(string name, ActivityKind kind);
11-
public Activity? StartChild(string name, ActivityKind kind, Activity? parent);
7+
Activity? Current { get; }
8+
Activity? StartSpan(string name, ActivityKind kind = ActivityKind.Internal);
129
}

TaskHub.Observability.Traces.Implementation/TracesService.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@ namespace TaskHub.Observability.Traces.Implementation;
55

66
public class TracesService(string serviceName) : ITracesService
77
{
8-
private readonly ActivitySource Source = new(serviceName);
8+
private readonly ActivitySource _source = new(serviceName);
9+
910
public Activity? Current => Activity.Current;
10-
public Activity? StartParent(string name) => Source.StartActivity(name, ActivityKind.Internal);
11-
public Activity? StartParent(string name, ActivityKind kind) => Source.StartActivity(name, kind);
12-
public Activity? StartChild(string name, ActivityKind kind) =>
13-
Source.StartActivity(name, kind, Current?.Context ?? default);
14-
public Activity? StartChild(string name, ActivityKind kind, Activity? parent) =>
15-
Source.StartActivity(name, kind, parent?.Context ?? default);
11+
12+
public Activity? StartSpan(string name, ActivityKind kind = ActivityKind.Internal) => _source.StartActivity(name, kind);
1613
}

TaskHub.Shared.Authorization.Identity/Bootstrap/AuthorizationService.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Microsoft.AspNetCore.Builder;
2-
using Microsoft.AspNetCore.Http;
1+
using Microsoft.AspNetCore.Http;
32
using Microsoft.Extensions.DependencyInjection;
43
using System.Security.Claims;
54
using TaskHub.Shared.Authorization.Abstractions;
@@ -9,7 +8,7 @@ namespace TaskHub.Shared.Authorization.Identity.Bootstrap;
98

109
public static class AuthorizationService
1110
{
12-
public static void AddAuthorizationService(this WebApplicationBuilder builder) => builder.Services.AddScoped<IUserService>(sp =>
11+
public static void AddAuthorizationService(this IServiceCollection services) => services.AddScoped<IUserService>(sp =>
1312
{
1413
var http = sp.GetRequiredService<IHttpContextAccessor>();
1514
var id = http.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? Guid.NewGuid().ToString();

TaskHub.Shared.Bootstraper/BasicHostBuilder.cs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,49 @@
66

77
namespace TaskHub.Shared.Bootstraper;
88

9-
public class BasicHostBuilder(string[] args)
9+
public class BasicHostBuilder
1010
{
11-
private readonly WebApplicationBuilder Builder = WebApplication.CreateBuilder(args);
11+
protected readonly WebApplicationBuilder Builder;
12+
protected readonly string ServiceName = string.Empty;
1213

13-
public void Init(Action<WebApplicationBuilder> action)
14+
public BasicHostBuilder(string[] args)
15+
{
16+
Builder = WebApplication.CreateBuilder(args);
17+
Builder.Configuration.AddJsonFile("appsettings.shared.json", false, true);
18+
Builder.Configuration.AddJsonFile("appsettings.json", false, true);
19+
ServiceName = Builder.Configuration.GetSection("OpenTelemetry:ServiceName").Get<string>() ?? string.Empty;
20+
}
21+
22+
public void Start() => AppStart();
23+
public virtual void Start(Action<WebApplicationBuilder> act)
24+
{
25+
AppStart();
26+
act(Builder);
27+
}
28+
29+
protected virtual void AppStart()
1430
{
15-
Builder.Configuration.Sources.Clear();
16-
Builder.Configuration
17-
.AddJsonFile("appsettings.shared.json", optional: false, reloadOnChange: false)
18-
.AddJsonFile("appsettings.json", optional: false)
19-
.AddJsonFile($"appsettings.{Builder.Environment.EnvironmentName}.json", optional: true);
2031
Builder.Services.AddControllers().AddJsonOptions(o => o.JsonSerializerOptions.PropertyNameCaseInsensitive = true);
2132
Builder.Services.AddEndpointsApiExplorer();
2233
Builder.Services.AddHttpContextAccessor();
2334
Builder.Services.AddDataProtection();
2435
Builder.Services.AddAuthentication();
2536
Builder.Services.ConfigureHttpJsonOptions(o => o.SerializerOptions.NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals);
26-
action(Builder);
37+
}
38+
39+
public async Task Run()
40+
{
41+
await BuildApp().RunAsync();
2742
}
2843

2944
public async Task Run(Func<WebApplication, Task> action)
45+
{
46+
var app = BuildApp();
47+
await action(app);
48+
await app.RunAsync();
49+
}
50+
51+
protected WebApplication BuildApp()
3052
{
3153
var app = Builder.Build();
3254

@@ -36,9 +58,12 @@ public async Task Run(Func<WebApplication, Task> action)
3658
}
3759

3860
app.UseHttpsRedirection();
61+
app.UseRouting();
3962
app.UseAuthentication();
4063
app.UseAuthorization();
41-
await action(app);
42-
await app.RunAsync();
64+
app.MapControllers();
65+
66+
return app;
4367
}
4468
}
69+

TaskHub.Shared.Bootstraper/FullHostBuilder.cs

Lines changed: 52 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
using Microsoft.Extensions.Configuration;
44
using Microsoft.Extensions.DependencyInjection;
55
using Prometheus;
6-
using System.Reflection;
76
using TaskHub.Observability.Logger.Serilog;
87
using TaskHub.Observability.Metrics.Implementation.Bootstrap;
98
using TaskHub.Observability.OpenTelemetry;
109
using TaskHub.Observability.Traces.Implementation;
1110
using TaskHub.Shared.Authorization.Identity.Bootstrap;
12-
using TaskHub.Shared.Bootstraper.Options;
1311
using TaskHub.Shared.Bootstraper.Settings;
1412
using TaskHub.Shared.Bootstraper.Setup;
1513
using TaskHub.Shared.Commands.Bus;
@@ -21,65 +19,69 @@
2119

2220
namespace TaskHub.Shared.Bootstraper;
2321

24-
public class FullHostBuilder(string[] args)
22+
public class FullHostBuilder(string[] args) : BasicHostBuilder(args)
2523
{
26-
private Action<WebApplication> _runAct = _ => { };
27-
private Action<WebApplicationBuilder> _initAct = _ => { };
24+
public async Task Start<TContext>() where TContext : DbContext
25+
{
26+
Builder.Services.AddAppDbContext<TContext>(Builder.Configuration, o => o.ConnectionString = "Default");
27+
AppStart();
28+
await Task.CompletedTask;
29+
}
2830

29-
public FullHostBuilder Add(Action<WebApplicationBuilder> act)
31+
public async Task Start<TContext>(Action<WebApplicationBuilder> act) where TContext : DbContext
3032
{
31-
_initAct = act;
32-
return this;
33+
Builder.Services.AddAppDbContext<TContext>(Builder.Configuration, o => o.ConnectionString = "Default");
34+
AppStart();
35+
act(Builder);
3336
}
3437

35-
public FullHostBuilder Use(Action<WebApplication> act)
38+
protected override void AppStart()
3639
{
37-
_runAct = act;
38-
return this;
40+
base.AppStart();
41+
var assms = AppDomain.CurrentDomain.GetAssemblies()
42+
.Where(a => !a.IsDynamic && a.GetName().Name!.StartsWith("TaskHub."))
43+
.SelectMany(a => a.GetTypes()).ToArray();
44+
45+
Builder.Services.AddAppOpenTelemetry(o => Builder.Configuration.GetSection("OpenTelemetry").Bind(o));
46+
Builder.Services.AddAppAuthorization(o => Builder.Configuration.GetSection("Jwt").Bind(o));
47+
Builder.Services.AddAppVersioning(o => Builder.Configuration.GetSection("Versioning").Bind(o));
48+
Builder.Services.AddAppRedis(o => Builder.Configuration.GetSection("Redis").Bind(o));
49+
Builder.Services.AddFixedRateLimiter(o => Builder.Configuration.GetSection("RateLimiter").Bind(o));
50+
Builder.Services.AddAppSwagger(o => Builder.Configuration.GetSection("Swagger").Bind(o));
51+
Builder.Services.AddAppTraces(ServiceName);
52+
Builder.Services.AddAppMetrics(Builder.Configuration);
53+
Builder.Services.AddAuthorizationService();
54+
Builder.Services.AddAppCommandsBus(assms);
55+
Builder.Services.AddAppUnitOfWork(assms);
56+
Builder.Services.AddAppRepositories(assms);
57+
Builder.Host.AddAppSerilog(ServiceName);
3958
}
4059

41-
public async Task StartWith<TContext>(Action<HostOptions> action) where TContext : DbContext
60+
public async Task Run<TContext>() where TContext : DbContext
4261
{
43-
var options = new HostOptions();
44-
action(options);
45-
var host = new BasicHostBuilder(args);
62+
var app = await BuildApp<TContext>();
63+
await app.RunAsync();
64+
}
4665

47-
SwaggerOptions? swagger = null;
48-
var serviceName = string.Empty;
49-
host.Init(builder =>
50-
{
51-
var assms = Directory.GetFiles(AppContext.BaseDirectory, "*.dll").Select(Assembly.LoadFrom).SelectMany(a => a.GetTypes());
52-
serviceName = builder.Configuration.GetSection("OpenTelemetry:ServiceName").Get<string>() ?? string.Empty;
53-
swagger = builder.Configuration.GetSection("Swagger").Get<SwaggerOptions>() ?? new();
54-
builder.Services.AddAppDbContext<TContext>(builder.Configuration, o => o.ConnectionString = options.ConnectionString);
55-
builder.Services.AddAppOpenTelemetry(o => builder.Configuration.GetSection("OpenTelemetry").Bind(o));
56-
builder.Services.AddAppAuthorization(o => builder.Configuration.GetSection("Jwt").Bind(o));
57-
builder.Services.AddAppVersioning(o => builder.Configuration.GetSection("Versioning").Bind(o));
58-
builder.Services.AddAppRedis(o => builder.Configuration.GetSection("Redis").Bind(0));
59-
builder.Services.AddFixedRateLimiter(o => builder.Configuration.GetSection("RateLimiter").Bind(o));
60-
builder.Services.AddAppSwagger(o => builder.Configuration.GetSection("Swagger").Bind(o));
61-
builder.Services.AddAppTraces(serviceName);
62-
builder.Services.AddAppMetrics(builder.Configuration);
63-
builder.Services.AddAppSerilog(builder.Configuration);
64-
builder.AddAuthorizationService();
65-
builder.Services.AddAppCommandsBus(assms);
66-
builder.Services.AddAppUnitOfWork(assms);
67-
builder.Services.AddAppRepositories(assms);
68-
assms = null;
69-
_initAct(builder);
70-
});
66+
public async Task Run<TContext>(Func<WebApplication, Task> action) where TContext : DbContext
67+
{
68+
var app = await BuildApp<TContext>();
69+
await action(app);
70+
await app.RunAsync();
71+
}
7172

72-
await host.Run(async app =>
73+
private async Task<WebApplication> BuildApp<TContext>() where TContext : DbContext
74+
{
75+
var app = BuildApp();
76+
77+
app.UseHttpMetrics(options =>
7378
{
74-
app.UseHttpMetrics(options =>
75-
{
76-
options.ReduceStatusCodeCardinality();
77-
options.AddCustomLabel("service", ctx => serviceName);
78-
});
79-
app.MapMetrics().AllowAnonymous();
80-
if (swagger != null) app.UseAppSwaggerUI(o => o = swagger);
81-
await app.Services.MigrateAsync<TContext>();
82-
_runAct(app);
79+
options.ReduceStatusCodeCardinality();
80+
options.AddCustomLabel("service", ctx => ServiceName);
8381
});
82+
83+
app.MapMetrics().AllowAnonymous();
84+
app.UseAppSwaggerUI(o => Builder.Configuration.GetSection("Swagger").Bind(o));
85+
return app;
8486
}
85-
}
87+
}

TaskHub.Shared.Bootstraper/Setup/AddRepositories.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace TaskHub.Shared.Bootstraper.Setup;
55

66
public static class AddRepositories
77
{
8-
public static void AddAppRepositories(this IServiceCollection services, IEnumerable<Type> types)
8+
public static void AddAppRepositories(this IServiceCollection services, Type[] types)
99
{
1010
var src = types.Where(t => t.IsInterface && typeof(IRepository).IsAssignableFrom(t));
1111
foreach (var item in src)

TaskHub.Shared.Bootstraper/Setup/AddUnitOfWork.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace TaskHub.Shared.Bootstraper.Setup;
55

66
public static class AddUnitOfWork
77
{
8-
public static void AddAppUnitOfWork(this IServiceCollection services, IEnumerable<Type> types)
8+
public static void AddAppUnitOfWork(this IServiceCollection services, Type[] types)
99
{
1010
var src = types.Where(t => t.IsInterface && typeof(IUnitOfWork).IsAssignableFrom(t));
1111
foreach (var item in src)

0 commit comments

Comments
 (0)