LCOV - code coverage report
Current view: top level - media/server/main/source - LogMetricsReporter.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 43 43
Test Date: 2026-09-11 17:36:12 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /*
       2              :  * If not stated otherwise in this file or this component's LICENSE file the
       3              :  * following copyright and licenses apply:
       4              :  *
       5              :  * Copyright 2026 Sky UK
       6              :  *
       7              :  * Licensed under the Apache License, Version 2.0 (the "License");
       8              :  * you may not use this file except in compliance with the License.
       9              :  * You may obtain a copy of the License at
      10              :  *
      11              :  * http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  * Unless required by applicable law or agreed to in writing, software
      14              :  * distributed under the License is distributed on an "AS IS" BASIS,
      15              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  * See the License for the specific language governing permissions and
      17              :  * limitations under the License.
      18              :  */
      19              : 
      20              : #include "LogMetricsReporter.h"
      21              : #include "RialtoServerLogging.h"
      22              : #include <algorithm>
      23              : #include <cinttypes>
      24              : #include <cmath>
      25              : 
      26              : namespace
      27              : {
      28              : constexpr std::uint64_t kActiveReportIntervalMs{10 * 60 * 1000};
      29              : constexpr double kRelativeChangeTolerance{0.10};
      30              : constexpr double kCpuChangeThresholdPercentagePoints{10.0};
      31              : constexpr double kMemoryAbsoluteFloorKb{1024.0};
      32              : } // namespace
      33              : 
      34              : namespace firebolt::rialto::server
      35              : {
      36           26 : void LogMetricsReporter::reportPeriodicSample(const PeriodicMetricsReport &report)
      37              : {
      38           26 :     if (!shouldReportPeriodicSample(report))
      39              :     {
      40            9 :         return;
      41              :     }
      42              : 
      43           17 :     RIALTO_SERVER_LOG_MIL("Metrics sample=%" PRIu64 ", reason=%s, app='%s', client_pid=%u, client_cpu=%.2f%%, "
      44              :                           "server_cpu=%.2f%%, combined_cpu=%.2f%%, client_cpu_ms=%" PRIu64 ", "
      45              :                           "server_cpu_ms=%" PRIu64 ", client_mem_kb=%" PRIu64 ", server_mem_kb=%" PRIu64 ", "
      46              :                           "shm_mem_kb=%" PRIu64 ", cgroup_mem_kb=%" PRIu64 "/%" PRIu64,
      47              :                           report.sampleId, report.reason.c_str(), report.appName.c_str(), report.clientPid,
      48              :                           report.clientCpuPercent, report.serverCpuPercent, report.combinedCpuPercent,
      49              :                           report.clientCpuTimeMs, report.serverCpuTimeMs, report.clientMemoryKb, report.serverMemoryKb,
      50              :                           report.shmMemoryKb, report.cgroupMemoryUsageKb, report.cgroupMemoryLimitKb);
      51              : }
      52              : 
      53           26 : bool LogMetricsReporter::shouldReportPeriodicSample(const PeriodicMetricsReport &report)
      54              : {
      55           26 :     std::lock_guard<std::mutex> lock{m_mutex};
      56              : 
      57           26 :     if (report.reason != "PERIODIC")
      58              :     {
      59            1 :         return false;
      60              :     }
      61              : 
      62           25 :     if (!m_lastReportedSample)
      63              :     {
      64            7 :         m_lastReportedSample = report;
      65            7 :         return true;
      66              :     }
      67              : 
      68           18 :     const auto &previous{*m_lastReportedSample};
      69           18 :     const bool stateChanged{report.applicationState != previous.applicationState};
      70              :     const bool metricsChanged{
      71           34 :         std::abs(report.clientCpuPercent - previous.clientCpuPercent) >= kCpuChangeThresholdPercentagePoints ||
      72           30 :         std::abs(report.serverCpuPercent - previous.serverCpuPercent) >= kCpuChangeThresholdPercentagePoints ||
      73           14 :         std::abs(report.combinedCpuPercent - previous.combinedCpuPercent) >= kCpuChangeThresholdPercentagePoints ||
      74           12 :         changedSignificantly(static_cast<double>(report.clientMemoryKb), static_cast<double>(previous.clientMemoryKb),
      75           11 :                              kMemoryAbsoluteFloorKb) ||
      76           11 :         changedSignificantly(static_cast<double>(report.serverMemoryKb), static_cast<double>(previous.serverMemoryKb),
      77           10 :                              kMemoryAbsoluteFloorKb) ||
      78           10 :         changedSignificantly(static_cast<double>(report.cgroupMemoryUsageKb),
      79           10 :                              static_cast<double>(previous.cgroupMemoryUsageKb), kMemoryAbsoluteFloorKb) ||
      80           10 :         changedSignificantly(static_cast<double>(report.cgroupMemoryLimitKb),
      81           44 :                              static_cast<double>(previous.cgroupMemoryLimitKb), kMemoryAbsoluteFloorKb) ||
      82           10 :         changedSignificantly(static_cast<double>(report.shmMemoryKb), static_cast<double>(previous.shmMemoryKb),
      83           18 :                              kMemoryAbsoluteFloorKb)};
      84           40 :     const bool activeIntervalElapsed{report.applicationState == ApplicationState::RUNNING &&
      85           22 :                                      report.monotonicTimeMs >= previous.monotonicTimeMs &&
      86            4 :                                      report.monotonicTimeMs - previous.monotonicTimeMs >= kActiveReportIntervalMs};
      87              : 
      88           18 :     if (stateChanged || metricsChanged || activeIntervalElapsed)
      89              :     {
      90           10 :         m_lastReportedSample = report;
      91           10 :         return true;
      92              :     }
      93              : 
      94            8 :     return false;
      95           26 : }
      96              : 
      97           53 : bool LogMetricsReporter::changedSignificantly(double current, double previous, double absoluteFloor)
      98              : {
      99           53 :     const double threshold{std::max(std::abs(previous) * kRelativeChangeTolerance, absoluteFloor)};
     100           53 :     return std::abs(current - previous) >= threshold;
     101              : }
     102              : 
     103            4 : void LogMetricsReporter::reportStateTransition(const StateTransitionReport &report)
     104              : {
     105            4 :     const auto &r{report.metrics};
     106            4 :     RIALTO_SERVER_LOG_MIL("Metrics state report [%s] state='%s', duration_ms=%" PRIu64 ", samples=%" PRIu64 ", "
     107              :                           "client_cpu={min=%.2f, max=%.2f, mean=%.2f, stddev=%.2f}%%, "
     108              :                           "server_cpu={min=%.2f, max=%.2f, mean=%.2f, stddev=%.2f}%%, "
     109              :                           "combined_cpu={min=%.2f, max=%.2f, mean=%.2f, stddev=%.2f}%%, "
     110              :                           "client_mem_kb={min=%.0f, max=%.0f, mean=%.0f}, "
     111              :                           "server_mem_kb={min=%.0f, max=%.0f, mean=%.0f}, "
     112              :                           "cgroup_mem_kb={min=%.0f, max=%.0f, mean=%.0f}",
     113              :                           report.context.c_str(), r.stateName.c_str(), r.durationMs, r.clientCpu.count, r.clientCpu.min,
     114              :                           r.clientCpu.max, r.clientCpu.mean, r.clientCpu.stddev, r.serverCpu.min, r.serverCpu.max,
     115              :                           r.serverCpu.mean, r.serverCpu.stddev, r.combinedCpu.min, r.combinedCpu.max,
     116              :                           r.combinedCpu.mean, r.combinedCpu.stddev, r.clientMemoryKb.min, r.clientMemoryKb.max,
     117              :                           r.clientMemoryKb.mean, r.serverMemoryKb.min, r.serverMemoryKb.max, r.serverMemoryKb.mean,
     118              :                           r.cgroupMemoryUsageKb.min, r.cgroupMemoryUsageKb.max, r.cgroupMemoryUsageKb.mean);
     119              : }
     120              : 
     121            1 : void LogMetricsReporter::reportThresholdExceeded(const ThresholdAlert &alert)
     122              : {
     123            1 :     const char *severity = (alert.severity == ThresholdSeverity::CRITICAL) ? "CRITICAL" : "WARNING";
     124            1 :     RIALTO_SERVER_LOG_WARN("Metrics threshold %s: %s=%.2f exceeds %.2f", severity, alert.metricName.c_str(),
     125              :                            alert.currentValue, alert.thresholdValue);
     126              : }
     127              : } // namespace firebolt::rialto::server
        

Generated by: LCOV version 2.0-1