-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathProgram.cs
More file actions
141 lines (118 loc) · 4.95 KB
/
Copy pathProgram.cs
File metadata and controls
141 lines (118 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2025 Datadog, Inc.
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Polly;
using Polly.Extensions.Http;
using Serilog;
using Serilog.Formatting.Json;
using Stickerlandia.PrintService.Client.Components;
using Stickerlandia.PrintService.Client.Configuration;
using Stickerlandia.PrintService.Client.Services;
using Stickerlandia.PrintService.Client.Telemetry;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddEnvironmentVariables();
// Configure Serilog
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.WriteTo.Console(new JsonFormatter())
.CreateLogger();
builder.Host.UseSerilog();
// Configure OpenTelemetry
var otlpEndpoint = builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"];
var resourceBuilder = ResourceBuilder.CreateDefault()
.AddService(
serviceName: PrintClientInstrumentation.ServiceName,
serviceVersion: PrintClientInstrumentation.ServiceVersion)
.AddAttributes([
new KeyValuePair<string, object>("deployment.environment",
builder.Configuration["ASPNETCORE_ENVIRONMENT"] ?? "development")
]);
builder.Services.AddSingleton<PrintClientInstrumentation>();
var otel = builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing
.SetResourceBuilder(resourceBuilder)
.AddSource(PrintClientInstrumentation.ServiceName)
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation(options =>
{
options.FilterHttpRequestMessage = (httpRequestMessage) =>
{
// Exclude any requests to the Datadog agent or localhost as they are likely related to telemetry export and not relevant for application tracing
var isDatadogHost = httpRequestMessage.RequestUri?.Host.Contains("datadog-agent", StringComparison.OrdinalIgnoreCase) ?? true;
var isLocalHost = httpRequestMessage.RequestUri?.Host.Contains("localhost", StringComparison.OrdinalIgnoreCase) ?? true;
return !isDatadogHost && !isLocalHost;
};
});
})
.WithMetrics(metrics =>
{
metrics
.SetResourceBuilder(resourceBuilder)
.AddMeter(PrintClientInstrumentation.ServiceName)
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation();
});
if (otlpEndpoint != null)
{
otel.UseOtlpExporter(OtlpExportProtocol.Grpc, new Uri(otlpEndpoint));
}
// Add Blazor services
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddSingleton<DatadogTransactionTracker>();
// Add configuration service (singleton - shared across app)
builder.Services.AddSingleton<IConfigurationService, ConfigurationService>();
// Add client status service (singleton - shared state for UI)
builder.Services.AddSingleton<ClientStatusService>();
// Add local storage service (singleton - caches jobs in memory)
builder.Services.AddSingleton<ILocalStorageService, LocalStorageService>();
// Configure HTTP client with retry policy
var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
builder.Services.AddHttpClient<IPrintServiceApiClient, PrintServiceApiClient>(client =>
{
// BaseAddress not set here - URLs are built dynamically from configuration
// to support runtime URL changes without restarting the application
client.Timeout = TimeSpan.FromSeconds(30);
})
.AddPolicyHandler(retryPolicy);
// Add background polling service
builder.Services.AddHostedService<PrintJobPollingService>();
var app = builder.Build();
// Configure the HTTP request pipeline
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
// Create default configuration if it doesn't exist and is configured
if (!string.IsNullOrEmpty(app.Configuration["DEFAULT_PRINTER_KEY"]))
{
var configService = app.Services.GetRequiredService<IConfigurationService>();
if (!ConfigurationService.ConfigurationExists())
{
await configService.SaveAsync(new PrinterClientConfig()
{
ApiKey = app.Configuration["DEFAULT_PRINTER_KEY"]!,
BackendUrl = app.Configuration["DEFAULT_BACKEND_URL"] ?? "http://localhost:8080",
PollingIntervalSeconds = 10,
MaxJobsPerPoll = 10
});
}
}
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
app.UseHttpsRedirection();
app.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
await app.RunAsync();