// Copyright Epic Games, Inc. All Rights Reserved. #include "inprocsessionlogsink.h" #include namespace zen { /// Bias in seconds from DateTime epoch (year 1) to Unix epoch (1970). static constexpr uint64_t UnixEpochBiasSeconds = uint64_t(double(1970 - 1) * 365.2425) * 86400; static DateTime TimePointToDateTime(logging::LogClock::time_point Time) { // DateTime ticks are 100 ns each. Splitting the time_point into whole-second // and sub-second parts and converting both lets us preserve sub-second // precision; the previous implementation truncated to seconds, which made // every entry land at .000 ms in tail / dashboard renderings. auto Duration = Time.time_since_epoch(); auto Seconds = std::chrono::duration_cast(Duration); auto SubSecondNanos = std::chrono::duration_cast(Duration - Seconds); uint64_t SecondsTicks = (UnixEpochBiasSeconds + static_cast(Seconds.count())) * TimeSpan::TicksPerSecond; uint64_t SubSecondTicks = static_cast(SubSecondNanos.count()) / static_cast(TimeSpan::NanosecondsPerTick); return DateTime{SecondsTicks + SubSecondTicks}; } void InProcSessionLogSink::Log(const logging::LogMessage& Msg) { // Route through the service-level AppendLog so the log-appended // callback fires — otherwise WS subscribers tailing the self-session // don't see in-proc lines until they reload and re-fetch via HTTP. m_Service.AppendLog(m_SessionId, SessionsService::LogEntryInput{ .Timestamp = TimePointToDateTime(Msg.GetTime()), .Level = Msg.GetLevel(), .LoggerName = Msg.GetLoggerName(), .Message = Msg.GetPayload(), }); } } // namespace zen