12498b56bSopenharmony_ci/*
22498b56bSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42498b56bSopenharmony_ci * you may not use this file except in compliance with the License.
52498b56bSopenharmony_ci * You may obtain a copy of the License at
62498b56bSopenharmony_ci *
72498b56bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82498b56bSopenharmony_ci *
92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122498b56bSopenharmony_ci * See the License for the specific language governing permissions and
132498b56bSopenharmony_ci * limitations under the License.
142498b56bSopenharmony_ci */
152498b56bSopenharmony_ci#include <thread>
162498b56bSopenharmony_ci#include <algorithm>
172498b56bSopenharmony_ci
182498b56bSopenharmony_ci#include <log_utils.h>
192498b56bSopenharmony_ci#include <properties.h>
202498b56bSopenharmony_ci
212498b56bSopenharmony_ci#include "log_stats.h"
222498b56bSopenharmony_ci
232498b56bSopenharmony_cinamespace OHOS {
242498b56bSopenharmony_cinamespace HiviewDFX {
252498b56bSopenharmony_ciusing namespace std;
262498b56bSopenharmony_ci
272498b56bSopenharmony_ciLogStats::LogStats()
282498b56bSopenharmony_ci{
292498b56bSopenharmony_ci    Reset();
302498b56bSopenharmony_ci    enable = IsStatsEnable();
312498b56bSopenharmony_ci    tagEnable = IsTagStatsEnable();
322498b56bSopenharmony_ci}
332498b56bSopenharmony_ciLogStats::~LogStats() {}
342498b56bSopenharmony_ci
352498b56bSopenharmony_cistatic inline int idxLvl(uint16_t lvl)
362498b56bSopenharmony_ci{
372498b56bSopenharmony_ci    return static_cast<int>(lvl) - LevelBase;
382498b56bSopenharmony_ci}
392498b56bSopenharmony_ci
402498b56bSopenharmony_cistatic void UpdateStats(StatsEntry &entry, const StatsInfo &info)
412498b56bSopenharmony_ci{
422498b56bSopenharmony_ci    LogTimeStamp ts_mono(info.mono_sec, info.tv_nsec);
432498b56bSopenharmony_ci    static LogTimeStamp ts_audit_period(1, 0); // Audit period : one second
442498b56bSopenharmony_ci    ts_mono -= entry.monoTimeLast;
452498b56bSopenharmony_ci    if (ts_mono > ts_audit_period) {
462498b56bSopenharmony_ci        entry.monoTimeLast -= entry.monoTimeAuditStart;
472498b56bSopenharmony_ci        float secs = entry.monoTimeLast.FloatSecs();
482498b56bSopenharmony_ci        if (secs < 1.0f) {
492498b56bSopenharmony_ci            secs = 1.0f;
502498b56bSopenharmony_ci        }
512498b56bSopenharmony_ci        float freq = entry.tmpLines / secs;
522498b56bSopenharmony_ci        if (freq > entry.freqMax) {
532498b56bSopenharmony_ci            entry.freqMax = freq;
542498b56bSopenharmony_ci            entry.realTimeFreqMax = entry.realTimeLast;
552498b56bSopenharmony_ci        }
562498b56bSopenharmony_ci        entry.tmpLines = 0;
572498b56bSopenharmony_ci        float throughput = entry.tmpLen / secs;
582498b56bSopenharmony_ci        if (throughput > entry.throughputMax) {
592498b56bSopenharmony_ci            entry.throughputMax = throughput;
602498b56bSopenharmony_ci            entry.realTimeThroughputMax = entry.realTimeLast;
612498b56bSopenharmony_ci        }
622498b56bSopenharmony_ci        entry.tmpLen = 0;
632498b56bSopenharmony_ci        entry.monoTimeAuditStart.SetTimeStamp(info.mono_sec, info.tv_nsec);
642498b56bSopenharmony_ci    }
652498b56bSopenharmony_ci
662498b56bSopenharmony_ci    int lvl = idxLvl(info.level);
672498b56bSopenharmony_ci    entry.lines[lvl]++;
682498b56bSopenharmony_ci    entry.len[lvl] += info.len;
692498b56bSopenharmony_ci    entry.dropped += info.dropped;
702498b56bSopenharmony_ci    entry.tmpLines++;
712498b56bSopenharmony_ci    entry.tmpLen += info.len;
722498b56bSopenharmony_ci    entry.monoTimeLast.SetTimeStamp(info.mono_sec, info.tv_nsec);
732498b56bSopenharmony_ci    entry.realTimeLast.SetTimeStamp(info.tv_sec, info.tv_nsec);
742498b56bSopenharmony_ci}
752498b56bSopenharmony_ci
762498b56bSopenharmony_cistatic void ResetStatsEntry(StatsEntry &entry)
772498b56bSopenharmony_ci{
782498b56bSopenharmony_ci    entry.dropped = 0;
792498b56bSopenharmony_ci    entry.tmpLines = 0;
802498b56bSopenharmony_ci    entry.freqMax = 0;
812498b56bSopenharmony_ci    entry.realTimeFreqMax.SetTimeStamp(0, 0);
822498b56bSopenharmony_ci    entry.tmpLen = 0;
832498b56bSopenharmony_ci    entry.throughputMax = 0;
842498b56bSopenharmony_ci    entry.realTimeThroughputMax.SetTimeStamp(0, 0);
852498b56bSopenharmony_ci    entry.monoTimeLast.SetTimeStamp(0, 0);
862498b56bSopenharmony_ci    entry.monoTimeAuditStart.SetTimeStamp(0, 0);
872498b56bSopenharmony_ci    for (uint32_t &i : entry.lines) {
882498b56bSopenharmony_ci        i = 0;
892498b56bSopenharmony_ci    }
902498b56bSopenharmony_ci    for (uint64_t &i : entry.len) {
912498b56bSopenharmony_ci        i = 0;
922498b56bSopenharmony_ci    }
932498b56bSopenharmony_ci}
942498b56bSopenharmony_ci
952498b56bSopenharmony_cistatic void StatsInfo2NewStatsEntry(const StatsInfo &info, StatsEntry &entry)
962498b56bSopenharmony_ci{
972498b56bSopenharmony_ci    entry.dropped = info.dropped;
982498b56bSopenharmony_ci    entry.tmpLines = 1;
992498b56bSopenharmony_ci    entry.freqMax = 0;
1002498b56bSopenharmony_ci    entry.realTimeFreqMax.SetTimeStamp(info.tv_sec, info.tv_nsec);
1012498b56bSopenharmony_ci    entry.tmpLen = info.len;
1022498b56bSopenharmony_ci    entry.throughputMax = 0;
1032498b56bSopenharmony_ci    entry.realTimeThroughputMax.SetTimeStamp(info.tv_sec, info.tv_nsec);
1042498b56bSopenharmony_ci    entry.realTimeLast.SetTimeStamp(info.tv_sec, info.tv_nsec);
1052498b56bSopenharmony_ci    entry.monoTimeLast.SetTimeStamp(info.mono_sec, info.tv_nsec);
1062498b56bSopenharmony_ci    entry.monoTimeAuditStart.SetTimeStamp(info.mono_sec, info.tv_nsec);
1072498b56bSopenharmony_ci    for (uint32_t &i : entry.lines) {
1082498b56bSopenharmony_ci        i = 0;
1092498b56bSopenharmony_ci    }
1102498b56bSopenharmony_ci    for (uint64_t &i : entry.len) {
1112498b56bSopenharmony_ci        i = 0;
1122498b56bSopenharmony_ci    }
1132498b56bSopenharmony_ci    int lvl = idxLvl(info.level);
1142498b56bSopenharmony_ci    entry.lines[lvl] = 1;
1152498b56bSopenharmony_ci    entry.len[lvl] = info.len;
1162498b56bSopenharmony_ci}
1172498b56bSopenharmony_ci
1182498b56bSopenharmony_civoid LogStats::UpdateTagTable(TagTable& tt, const StatsInfo &info)
1192498b56bSopenharmony_ci{
1202498b56bSopenharmony_ci    if (!tagEnable) {
1212498b56bSopenharmony_ci        return;
1222498b56bSopenharmony_ci    }
1232498b56bSopenharmony_ci    auto itt = tt.find(info.tag);
1242498b56bSopenharmony_ci    if (itt != tt.end()) {
1252498b56bSopenharmony_ci        UpdateStats(itt->second, info);
1262498b56bSopenharmony_ci    } else {
1272498b56bSopenharmony_ci        TagStatsEntry entry;
1282498b56bSopenharmony_ci        StatsInfo2NewStatsEntry(info, entry);
1292498b56bSopenharmony_ci        (void)tt.emplace(info.tag, entry);
1302498b56bSopenharmony_ci    }
1312498b56bSopenharmony_ci}
1322498b56bSopenharmony_ci
1332498b56bSopenharmony_civoid LogStats::UpdateDomainTable(const StatsInfo &info)
1342498b56bSopenharmony_ci{
1352498b56bSopenharmony_ci    DomainTable& t = domainStats[info.type];
1362498b56bSopenharmony_ci    auto it = t.find(info.domain);
1372498b56bSopenharmony_ci    if (it != t.end()) {
1382498b56bSopenharmony_ci        UpdateStats(it->second.stats, info);
1392498b56bSopenharmony_ci    } else {
1402498b56bSopenharmony_ci        DomainStatsEntry entry;
1412498b56bSopenharmony_ci        StatsInfo2NewStatsEntry(info, entry.stats);
1422498b56bSopenharmony_ci        auto result = t.emplace(info.domain, entry);
1432498b56bSopenharmony_ci        if (!result.second) {
1442498b56bSopenharmony_ci            cerr << "Add entry to DomainTable error" << endl;
1452498b56bSopenharmony_ci            return;
1462498b56bSopenharmony_ci        }
1472498b56bSopenharmony_ci        it = result.first;
1482498b56bSopenharmony_ci    }
1492498b56bSopenharmony_ci    UpdateTagTable(it->second.tagStats, info);
1502498b56bSopenharmony_ci}
1512498b56bSopenharmony_ci
1522498b56bSopenharmony_civoid LogStats::UpdatePidTable(const StatsInfo &info)
1532498b56bSopenharmony_ci{
1542498b56bSopenharmony_ci    PidTable& t = pidStats;
1552498b56bSopenharmony_ci    auto it = t.find(info.pid);
1562498b56bSopenharmony_ci    if (it != t.end()) {
1572498b56bSopenharmony_ci        UpdateStats(it->second.statsAll, info);
1582498b56bSopenharmony_ci        UpdateStats(it->second.stats[info.type], info);
1592498b56bSopenharmony_ci    } else {
1602498b56bSopenharmony_ci        PidStatsEntry entry;
1612498b56bSopenharmony_ci        StatsInfo2NewStatsEntry(info, entry.statsAll);
1622498b56bSopenharmony_ci        for (StatsEntry &e : entry.stats) {
1632498b56bSopenharmony_ci            ResetStatsEntry(e);
1642498b56bSopenharmony_ci        }
1652498b56bSopenharmony_ci        entry.stats[info.type] = entry.statsAll;
1662498b56bSopenharmony_ci        entry.name = GetNameByPid(info.pid);
1672498b56bSopenharmony_ci        auto result = t.emplace(info.pid, entry);
1682498b56bSopenharmony_ci        if (!result.second) {
1692498b56bSopenharmony_ci            cerr << "Add entry to PidTable error" << endl;
1702498b56bSopenharmony_ci            return;
1712498b56bSopenharmony_ci        }
1722498b56bSopenharmony_ci        it = result.first;
1732498b56bSopenharmony_ci    }
1742498b56bSopenharmony_ci    UpdateTagTable(it->second.tagStats, info);
1752498b56bSopenharmony_ci}
1762498b56bSopenharmony_ci
1772498b56bSopenharmony_civoid LogStats::Count(const StatsInfo &info)
1782498b56bSopenharmony_ci{
1792498b56bSopenharmony_ci    if (enable) {
1802498b56bSopenharmony_ci        std::scoped_lock lk(lock);
1812498b56bSopenharmony_ci        int index = idxLvl(info.level);
1822498b56bSopenharmony_ci        totalLines[index]++;
1832498b56bSopenharmony_ci        totalLens[index] += info.len;
1842498b56bSopenharmony_ci        UpdateDomainTable(info);
1852498b56bSopenharmony_ci        UpdatePidTable(info);
1862498b56bSopenharmony_ci    }
1872498b56bSopenharmony_ci}
1882498b56bSopenharmony_ci
1892498b56bSopenharmony_civoid LogStats::Reset()
1902498b56bSopenharmony_ci{
1912498b56bSopenharmony_ci    std::scoped_lock lk(lock);
1922498b56bSopenharmony_ci    for (auto &t : domainStats) {
1932498b56bSopenharmony_ci        t.clear();
1942498b56bSopenharmony_ci    }
1952498b56bSopenharmony_ci    pidStats.clear();
1962498b56bSopenharmony_ci    tsBegin = LogTimeStamp(CLOCK_REALTIME);
1972498b56bSopenharmony_ci    monoBegin = LogTimeStamp(CLOCK_MONOTONIC);
1982498b56bSopenharmony_ci    for (int i = 0; i < LevelNum; i++) {
1992498b56bSopenharmony_ci        totalLines[i] = 0;
2002498b56bSopenharmony_ci        totalLens[i] = 0;
2012498b56bSopenharmony_ci    }
2022498b56bSopenharmony_ci}
2032498b56bSopenharmony_ci
2042498b56bSopenharmony_ciconst LogTypeDomainTable& LogStats::GetDomainTable() const
2052498b56bSopenharmony_ci{
2062498b56bSopenharmony_ci    return domainStats;
2072498b56bSopenharmony_ci}
2082498b56bSopenharmony_ci
2092498b56bSopenharmony_ciconst PidTable& LogStats::GetPidTable() const
2102498b56bSopenharmony_ci{
2112498b56bSopenharmony_ci    return pidStats;
2122498b56bSopenharmony_ci}
2132498b56bSopenharmony_ci
2142498b56bSopenharmony_ciconst LogTimeStamp& LogStats::GetBeginTs() const
2152498b56bSopenharmony_ci{
2162498b56bSopenharmony_ci    return tsBegin;
2172498b56bSopenharmony_ci}
2182498b56bSopenharmony_ci
2192498b56bSopenharmony_ciconst LogTimeStamp& LogStats::GetBeginMono() const
2202498b56bSopenharmony_ci{
2212498b56bSopenharmony_ci    return monoBegin;
2222498b56bSopenharmony_ci}
2232498b56bSopenharmony_ci
2242498b56bSopenharmony_civoid LogStats::GetTotalLines(uint32_t (&in_lines)[LevelNum]) const
2252498b56bSopenharmony_ci{
2262498b56bSopenharmony_ci    std::copy(totalLines, totalLines + LevelNum, in_lines);
2272498b56bSopenharmony_ci}
2282498b56bSopenharmony_ci
2292498b56bSopenharmony_civoid LogStats::GetTotalLens(uint64_t (&in_lens)[LevelNum]) const
2302498b56bSopenharmony_ci{
2312498b56bSopenharmony_ci    std::copy(totalLens, totalLens + LevelNum, in_lens);
2322498b56bSopenharmony_ci}
2332498b56bSopenharmony_ci
2342498b56bSopenharmony_cibool LogStats::IsEnable() const
2352498b56bSopenharmony_ci{
2362498b56bSopenharmony_ci    return enable;
2372498b56bSopenharmony_ci}
2382498b56bSopenharmony_ci
2392498b56bSopenharmony_cibool LogStats::IsTagEnable() const
2402498b56bSopenharmony_ci{
2412498b56bSopenharmony_ci    return tagEnable;
2422498b56bSopenharmony_ci}
2432498b56bSopenharmony_ci
2442498b56bSopenharmony_cistd::unique_lock<std::mutex> LogStats::GetLock()
2452498b56bSopenharmony_ci{
2462498b56bSopenharmony_ci    std::unique_lock<std::mutex> lk(lock);
2472498b56bSopenharmony_ci    return lk;
2482498b56bSopenharmony_ci}
2492498b56bSopenharmony_ci
2502498b56bSopenharmony_civoid LogStats::Print()
2512498b56bSopenharmony_ci{
2522498b56bSopenharmony_ci    cout << "Domain Table:" << endl;
2532498b56bSopenharmony_ci    int i = 0;
2542498b56bSopenharmony_ci    for (auto &t : domainStats) {
2552498b56bSopenharmony_ci        i++;
2562498b56bSopenharmony_ci        if (t.size() == 0) {
2572498b56bSopenharmony_ci            continue;
2582498b56bSopenharmony_ci        }
2592498b56bSopenharmony_ci        cout << "  Log type:" << (i - 1) << endl;
2602498b56bSopenharmony_ci        for (auto &it : t) {
2612498b56bSopenharmony_ci            cout << "    Domain: 0x" << std::hex << it.first << std::dec << endl;
2622498b56bSopenharmony_ci            cout << "      ";
2632498b56bSopenharmony_ci            it.second.stats.Print();
2642498b56bSopenharmony_ci            for (auto &itt : it.second.tagStats) {
2652498b56bSopenharmony_ci                cout << "      Tag: " << itt.first << endl;
2662498b56bSopenharmony_ci                cout << "        ";
2672498b56bSopenharmony_ci                itt.second.Print();
2682498b56bSopenharmony_ci            }
2692498b56bSopenharmony_ci        }
2702498b56bSopenharmony_ci    }
2712498b56bSopenharmony_ci    cout << "Pid Table:" << endl;
2722498b56bSopenharmony_ci    for (auto &t : pidStats) {
2732498b56bSopenharmony_ci        cout << "  Proc: " << t.second.name << "(" << t.first << ")" << endl;
2742498b56bSopenharmony_ci        cout << "    ";
2752498b56bSopenharmony_ci        t.second.statsAll.Print();
2762498b56bSopenharmony_ci        int i = 0;
2772498b56bSopenharmony_ci        for (auto &s : t.second.stats) {
2782498b56bSopenharmony_ci            i++;
2792498b56bSopenharmony_ci            if (s.GetTotalLines() == 0) {
2802498b56bSopenharmony_ci                continue;
2812498b56bSopenharmony_ci            }
2822498b56bSopenharmony_ci            cout << "      Log Type: " << (i - 1) << endl;
2832498b56bSopenharmony_ci            cout << "        ";
2842498b56bSopenharmony_ci            s.Print();
2852498b56bSopenharmony_ci        }
2862498b56bSopenharmony_ci        for (auto &itt : t.second.tagStats) {
2872498b56bSopenharmony_ci            cout << "      Tag: " << itt.first << endl;
2882498b56bSopenharmony_ci            cout << "        ";
2892498b56bSopenharmony_ci            itt.second.Print();
2902498b56bSopenharmony_ci        }
2912498b56bSopenharmony_ci    }
2922498b56bSopenharmony_ci}
2932498b56bSopenharmony_ci} // namespace HiviewDFX
2942498b56bSopenharmony_ci} // namespace OHOS