// Copyright Epic Games, Inc. All Rights Reserved. #include "logging.h" #include "config/config.h" #include #include #include #include #include #include #include #include #include #include #include #include "otlphttp.h" namespace zen { void InitializeServerLogging(const ZenServerConfig& InOptions, bool WithCacheService) { ZEN_MEMSCOPE(ELLMTag::Logging); const LoggingOptions LogOptions = {.IsDebug = InOptions.IsDebug, .IsVerbose = false, .IsTest = InOptions.IsTest, .NoConsoleOutput = InOptions.LoggingConfig.NoConsoleOutput, .QuietConsole = InOptions.LoggingConfig.QuietConsole, .ForceColor = InOptions.LoggingConfig.ForceColor, .AbsLogFile = InOptions.LoggingConfig.AbsLogFile, .LogId = InOptions.LoggingConfig.LogId}; BeginInitializeLogging(LogOptions); // Initialize loggers auto FileSink = GetFileSink(); // HTTP server request logging std::filesystem::path HttpLogPath = InOptions.DataDir / "logs" / "http.log"; zen::CreateDirectories(HttpLogPath.parent_path()); logging::SinkPtr HttpSink(new zen::logging::RotatingFileSink(HttpLogPath, /* max size */ 128 * 1024 * 1024, /* max files */ 16, /* rotate on open */ true)); Ref HttpLogger(new logging::Logger("http_requests", HttpSink)); logging::Registry::Instance().Register(HttpLogger); if (WithCacheService) { // Cache request logging std::filesystem::path CacheLogPath = InOptions.DataDir / "logs" / "z$.log"; zen::CreateDirectories(CacheLogPath.parent_path()); logging::SinkPtr CacheSink(new zen::logging::RotatingFileSink(CacheLogPath, /* max size */ 128 * 1024 * 1024, /* max files */ 16, /* rotate on open */ false)); Ref CacheLogger(new logging::Logger("z$", CacheSink)); logging::Registry::Instance().Register(CacheLogger); // Jupiter - only log upstream HTTP traffic to file Ref JupiterLogger(new logging::Logger("jupiter", FileSink)); logging::Registry::Instance().Register(JupiterLogger); // Zen - only log upstream HTTP traffic to file Ref ZenClientLogger(new logging::Logger("zenclient", FileSink)); logging::Registry::Instance().Register(ZenClientLogger); } Ref BroadcastSink = GetDefaultBroadcastSink(); #if ZEN_WITH_OTEL if (BroadcastSink && !InOptions.LoggingConfig.OtelEndpointUri.empty()) { // TODO: Should sanity check that endpoint is reachable? Also, a valid URI? logging::SinkPtr OtelSink(new zen::logging::OtelHttpProtobufSink(InOptions.LoggingConfig.OtelEndpointUri)); BroadcastSink->AddSink(std::move(OtelSink)); } #endif if (BroadcastSink && !InOptions.LoggingConfig.LogStreamEndpoint.empty()) { std::string Endpoint = InOptions.LoggingConfig.LogStreamEndpoint; std::string Host = "localhost"; uint16_t Port = 0; auto ColonPos = Endpoint.rfind(':'); if (ColonPos != std::string::npos) { Host = Endpoint.substr(0, ColonPos); std::optional P = ParseInt(std::string_view(Endpoint).substr(ColonPos + 1)); Port = P.value_or(0); } if (Port > 0) { logging::SinkPtr StreamSink(new TcpLogStreamSink(Host, Port, "zenserver")); BroadcastSink->AddSink(std::move(StreamSink)); } } FinishInitializeLogging(LogOptions); const zen::Oid ServerSessionId = zen::GetSessionId(); logging::Registry::Instance().ApplyAll([&](auto Logger) { static constinit logging::LogPoint SessionIdPoint{{}, logging::Info, "server session id: {}"}; ZEN_MEMSCOPE(ELLMTag::Logging); Logger->Log(SessionIdPoint, fmt::make_format_args(ServerSessionId)); }); } void ShutdownServerLogging() { ZEN_MEMSCOPE(ELLMTag::Logging); zen::ShutdownLogging(); } } // namespace zen