-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathProgram.cs
More file actions
75 lines (70 loc) · 3.28 KB
/
Copy pathProgram.cs
File metadata and controls
75 lines (70 loc) · 3.28 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
global using System;
using System.IO;
using System.Text;
using System.Threading;
using Coflnet.Core;
using Coflnet.Security.OpenBao;
using Coflnet.Sky.Core;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace Coflnet.Sky.PlayerState
{
public class Program
{
public static void Main(string[] args)
{
BufferConsoleOutput();
Console.WriteLine("uuid: " + new Guid("9b5f43a35815412f837f99944af4faf8"));
// ILogger output is shipped to Loki via OTLP (see AddOpenTelemetryLogging), not stdout.
// `kubectl logs` only shows this boot banner; query application logs in Loki, e.g.:
// {service_name="sky-player-state"} | detected_level="Error"
Console.WriteLine("[logs] application logs go to Loki, not stdout. Query: {service_name=\"sky-player-state\"} (Grafana > Explore > Loki)");
CreateHostBuilder(args).Build().Run();
}
/// <summary>
/// The default <see cref="Console.Out"/> flushes to stdout on every write, i.e. a
/// syscall taken under a process-global lock. With hundreds of hot-path log lines
/// per second across concurrently processed messages that lock serialises
/// processing. Wrap stdout in a buffered writer flushed periodically (and on exit)
/// so logging stops being a throughput bottleneck while still reaching the log
/// collector within a fraction of a second.
/// </summary>
private static void BufferConsoleOutput()
{
var bufferedOut = new StreamWriter(Console.OpenStandardOutput(), new UTF8Encoding(false), 1 << 16)
{
AutoFlush = false
};
var syncedOut = TextWriter.Synchronized(bufferedOut);
Console.SetOut(syncedOut);
var flushInterval = TimeSpan.FromMilliseconds(500);
var flushTimer = new Timer(_ =>
{
try { syncedOut.Flush(); } catch { /* stdout closed during shutdown */ }
}, null, flushInterval, flushInterval);
GC.KeepAlive(flushTimer);
void Flush(object sender, EventArgs e)
{
try { syncedOut.Flush(); } catch { /* best effort on shutdown/crash */ }
}
AppDomain.CurrentDomain.ProcessExit += Flush;
AppDomain.CurrentDomain.UnhandledException += (s, e) => Flush(s, e);
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((_, config) => config.AddOpenBaoFromEnvironment())
.ConfigureLogging((context, logging) =>
{
// Shared OTel logging configuration from Coflnet.Core.
// Bridges ILogger -> OTLP (HttpProtobuf) with trace-log correlation,
// k8s pod attributes, and DEV_LOGGING console fallback.
logging.AddOpenTelemetryLogging(
context.Configuration,
context.Configuration["JAEGER_SERVICE_NAME"] ?? "sky-player-state");
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}