| | 1 | | // PaymentService/Program.cs (ajustado com TraceId, Serilog, OpenTelemetry compatível) |
| | 2 | | using MassTransit; |
| | 3 | | using Microsoft.EntityFrameworkCore; |
| | 4 | | using PaymentService; |
| | 5 | | using Polly; |
| | 6 | | using Serilog; |
| | 7 | | using Contracts.Observability; |
| | 8 | | using OpenTelemetry; |
| | 9 | | using OpenTelemetry.Context.Propagation; |
| | 10 | | using OpenTelemetry.Exporter; |
| | 11 | | using OpenTelemetry.Resources; |
| | 12 | | using OpenTelemetry.Trace; |
| | 13 | | using System.Diagnostics; |
| | 14 | |
|
| 0 | 15 | | var builder = Host.CreateApplicationBuilder(args); |
| | 16 | |
|
| | 17 | | // Inicializa Serilog com TraceId/SpanId |
| 0 | 18 | | Log.Logger = new LoggerConfiguration() |
| 0 | 19 | | .MinimumLevel.Debug() |
| 0 | 20 | | .Enrich.FromLogContext() |
| 0 | 21 | | .Enrich.With<ActivityEnricher>() |
| 0 | 22 | | .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} TraceId={TraceId} SpanId={SpanId}{N |
| 0 | 23 | | .CreateLogger(); |
| | 24 | |
|
| 0 | 25 | | builder.Logging.ClearProviders(); |
| 0 | 26 | | builder.Logging.AddSerilog(); |
| | 27 | |
|
| | 28 | | // Configuração do OpenTelemetry com propagação e exportação para Jaeger (versão compatível) |
| 0 | 29 | | Sdk.SetDefaultTextMapPropagator(new TraceContextPropagator()); |
| | 30 | |
|
| 0 | 31 | | builder.Services.AddOpenTelemetry() |
| 0 | 32 | | .WithTracing(builder => |
| 0 | 33 | | { |
| 0 | 34 | | builder |
| 0 | 35 | | .AddAspNetCoreInstrumentation() |
| 0 | 36 | | .AddHttpClientInstrumentation() |
| 0 | 37 | | .AddSource("PaymentService") |
| 0 | 38 | | .AddSource("MassTransit") |
| 0 | 39 | | .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("PaymentService")) |
| 0 | 40 | | .AddOtlpExporter(o => |
| 0 | 41 | | { |
| 0 | 42 | | o.Endpoint = new Uri("http://jaeger:4317"); // Jaeger OTLP endpoint |
| 0 | 43 | | o.Protocol = OtlpExportProtocol.Grpc; |
| 0 | 44 | | }); |
| 0 | 45 | | }); |
| | 46 | |
|
| 0 | 47 | | builder.Services.AddDbContext<PaymentDbContext>((provider, options) => |
| 0 | 48 | | { |
| 0 | 49 | | var configuration = provider.GetRequiredService<IConfiguration>(); |
| 0 | 50 | | options.UseNpgsql(configuration.GetConnectionString("DefaultConnection")); |
| 0 | 51 | | }); |
| | 52 | |
|
| | 53 | |
|
| 0 | 54 | | builder.Services.AddMassTransit(x => |
| 0 | 55 | | { |
| 0 | 56 | | x.AddConsumer<OrderConsumer>(); |
| 0 | 57 | |
|
| 0 | 58 | | x.UsingRabbitMq((ctx, cfg) => |
| 0 | 59 | | { |
| 0 | 60 | | cfg.Host("rabbitmq", "/", h => |
| 0 | 61 | | { |
| 0 | 62 | | h.Username("guest"); |
| 0 | 63 | | h.Password("guest"); |
| 0 | 64 | | }); |
| 0 | 65 | |
|
| 0 | 66 | | cfg.ReceiveEndpoint("payment-service-queue", e => |
| 0 | 67 | | { |
| 0 | 68 | | e.ConfigureConsumer<OrderConsumer>(ctx); |
| 0 | 69 | | }); |
| 0 | 70 | | }); |
| 0 | 71 | | }); |
| | 72 | |
|
| 0 | 73 | | builder.Services.AddHostedService<Worker>(); |
| 0 | 74 | | builder.Services.AddScoped<OrderConsumer>(); |
| | 75 | |
|
| 0 | 76 | | var app = builder.Build(); |
| | 77 | |
|
| | 78 | | // Retry com Polly para garantir que o banco esteja pronto |
| 0 | 79 | | var retryPolicy = Policy |
| 0 | 80 | | .Handle<Exception>() |
| 0 | 81 | | .WaitAndRetry( |
| 0 | 82 | | retryCount: 5, |
| 0 | 83 | | sleepDurationProvider: attempt => TimeSpan.FromSeconds(5), |
| 0 | 84 | | onRetry: (exception, time, retryCount, context) => |
| 0 | 85 | | { |
| 0 | 86 | | Log.Warning("[Polly] Tentativa {RetryCount}: aguardando {Seconds}s - erro: {Message}", |
| 0 | 87 | | retryCount, time.TotalSeconds, exception.Message); |
| 0 | 88 | | }); |
| | 89 | |
|
| 0 | 90 | | retryPolicy.Execute(() => |
| 0 | 91 | | { |
| 0 | 92 | | using var scope = app.Services.CreateScope(); |
| 0 | 93 | | var db = scope.ServiceProvider.GetRequiredService<PaymentDbContext>(); |
| 0 | 94 | | db.Database.Migrate(); |
| 0 | 95 | | }); |
| | 96 | |
|
| | 97 | | try |
| | 98 | | { |
| 0 | 99 | | Log.Information("🚀 PaymentService iniciado"); |
| 0 | 100 | | app.Run(); |
| 0 | 101 | | } |
| 0 | 102 | | catch (Exception ex) |
| | 103 | | { |
| 0 | 104 | | Log.Fatal(ex, "A aplicação terminou inesperadamente"); |
| 0 | 105 | | } |
| | 106 | | finally |
| | 107 | | { |
| 0 | 108 | | Log.CloseAndFlush(); |
| 0 | 109 | | } |