1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef OHOS_ROSEN_SCREEN_EVENT_TRACKER_H
17#define OHOS_ROSEN_SCREEN_EVENT_TRACKER_H
18
19#include <iomanip>
20#include <vector>
21#include <mutex>
22#include <sstream>
23#include <string>
24
25#include "window_manager_hilog.h"
26
27namespace OHOS {
28namespace Rosen {
29const int32_t OUTPUT_FREQ = 1; // 1Hz
30
31struct TrackInfo {
32    std::string info;
33    std::chrono::system_clock::time_point timestamp;
34};
35
36class EventTracker {
37public:
38    void RecordEvent(std::string info = "")
39    {
40        std::lock_guard<std::mutex> lock(mutex_);
41        recordInfos_.push_back({info, std::chrono::system_clock::now()});
42    }
43
44    void ClearAllRecordedEvents()
45    {
46        std::lock_guard<std::mutex> lock(mutex_);
47        recordInfos_.clear();
48    }
49
50    void LogWarningAllInfos() const
51    {
52        auto now = std::chrono::system_clock::now();
53        if (std::chrono::duration_cast<std::chrono::seconds>(now - lastOutputTime_).count() < OUTPUT_FREQ) {
54            return ; // Output too frequent. Try again later.
55        }
56        lastOutputTime_ = now;
57
58        std::lock_guard<std::mutex> lock(mutex_);
59        for (const auto& info : recordInfos_) {
60            TLOGW(WmsLogTag::DMS, "[%{public}s]: %{public}s",
61                formatTimestamp(info.timestamp).c_str(), info.info.c_str());
62        }
63    }
64
65    std::string formatTimestamp(const std::chrono::system_clock::time_point& timePoint) const
66    {
67        const int32_t WIDTH_TIME = 2;
68        const int32_t WIDTH_TIME_MS = 3;
69        const int32_t TIME_CONVERT_MS = 1000;
70        const char DEFAULT_CHAR = '0';
71        auto time = std::chrono::system_clock::to_time_t(timePoint);
72        std::tm localTime;
73        localtime_r(&time, &localTime);
74        auto timeMs = std::chrono::duration_cast<std::chrono::milliseconds>(
75            timePoint.time_since_epoch()) % TIME_CONVERT_MS;
76
77        std::ostringstream oss;
78        oss << std::setfill(DEFAULT_CHAR)
79            << std::setw(WIDTH_TIME) << (localTime.tm_mon + 1) << '-'
80            << std::setw(WIDTH_TIME) << localTime.tm_mday << ' '
81            << std::setw(WIDTH_TIME) << localTime.tm_hour << ':'
82            << std::setw(WIDTH_TIME) << localTime.tm_min << ':'
83            << std::setw(WIDTH_TIME) << localTime.tm_sec << '.'
84            << std::setw(WIDTH_TIME_MS) << timeMs.count();
85        return oss.str();
86    }
87
88    const std::vector<TrackInfo>& GetRecordInfos() const
89    {
90        std::lock_guard<std::mutex> lock(mutex_);
91        return recordInfos_;
92    }
93
94private:
95    mutable std::mutex mutex_;
96    mutable std::chrono::system_clock::time_point lastOutputTime_;
97    std::vector<TrackInfo> recordInfos_;
98};
99
100
101} // Rosen
102} // OHOS
103#endif // OHOS_ROSEN_SCREEN_EVENT_TRACKER_H