106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#ifndef _HHLOG_H
1706f6ba60Sopenharmony_ci#define _HHLOG_H
1806f6ba60Sopenharmony_ci
1906f6ba60Sopenharmony_ci#include <atomic>
2006f6ba60Sopenharmony_ci#include <cstdio>
2106f6ba60Sopenharmony_ci#include <cstring>
2206f6ba60Sopenharmony_ci#include <ctime>
2306f6ba60Sopenharmony_ci#include <iostream>
2406f6ba60Sopenharmony_ci#include <memory>
2506f6ba60Sopenharmony_ci#include <sstream>
2606f6ba60Sopenharmony_ci#include <string>
2706f6ba60Sopenharmony_ci#include <strstream>
2806f6ba60Sopenharmony_ci#include <thread>
2906f6ba60Sopenharmony_ci
3006f6ba60Sopenharmony_ci#include <fcntl.h>
3106f6ba60Sopenharmony_ci#include <securec.h>
3206f6ba60Sopenharmony_ci#include <stdarg.h>
3306f6ba60Sopenharmony_ci#include <unistd.h>
3406f6ba60Sopenharmony_ci#include <sys/time.h>
3506f6ba60Sopenharmony_ci
3606f6ba60Sopenharmony_ci#include "ringbuffer.h"
3706f6ba60Sopenharmony_ci
3806f6ba60Sopenharmony_cienum HHLOG_LEVEL:int {
3906f6ba60Sopenharmony_ci    HHLOG_DEBUG = 0,
4006f6ba60Sopenharmony_ci    HHLOG_INFO = 1,
4106f6ba60Sopenharmony_ci    HHLOG_WARN = 2,
4206f6ba60Sopenharmony_ci    HHLOG_ERROR = 3,
4306f6ba60Sopenharmony_ci    HHLOG_FATAL = 4,
4406f6ba60Sopenharmony_ci    HHLOG_NONE = 5,
4506f6ba60Sopenharmony_ci};
4606f6ba60Sopenharmony_ci
4706f6ba60Sopenharmony_ciclass HHLogger {
4806f6ba60Sopenharmony_cipublic:
4906f6ba60Sopenharmony_ci    ~HHLogger();
5006f6ba60Sopenharmony_ci    static inline HHLogger& GetInstance()
5106f6ba60Sopenharmony_ci    {
5206f6ba60Sopenharmony_ci        static HHLogger logger {};
5306f6ba60Sopenharmony_ci        return logger;
5406f6ba60Sopenharmony_ci    }
5506f6ba60Sopenharmony_ci
5606f6ba60Sopenharmony_ci    int Start(const int logLevel = HHLOG_DEBUG, const std::string& logFile = "./hhlog.txt");
5706f6ba60Sopenharmony_ci
5806f6ba60Sopenharmony_ci    inline int PutLog(const char* format, ...)
5906f6ba60Sopenharmony_ci    {
6006f6ba60Sopenharmony_ci        va_list args;
6106f6ba60Sopenharmony_ci        va_start(args, format);
6206f6ba60Sopenharmony_ci        auto ftime = GetFormatTime();
6306f6ba60Sopenharmony_ci        std::size_t nbytes = ftime.length();
6406f6ba60Sopenharmony_ci        if (nbytes == 0 or nbytes >= MAX_HHLOG_SIZE) {
6506f6ba60Sopenharmony_ci            return -1;
6606f6ba60Sopenharmony_ci        }
6706f6ba60Sopenharmony_ci        char buffer[MAX_HHLOG_SIZE];
6806f6ba60Sopenharmony_ci        if (memcpy_s(buffer, sizeof(buffer), ftime.c_str(), nbytes) != EOK) {
6906f6ba60Sopenharmony_ci            return -1;
7006f6ba60Sopenharmony_ci        }
7106f6ba60Sopenharmony_ci        int ret = vsnprintf_s(buffer + nbytes, sizeof(buffer) - nbytes,
7206f6ba60Sopenharmony_ci                              sizeof(buffer) - nbytes - 1, format, args);
7306f6ba60Sopenharmony_ci        va_end(args);
7406f6ba60Sopenharmony_ci        if (ret < 0) {
7506f6ba60Sopenharmony_ci            return -1;
7606f6ba60Sopenharmony_ci        }
7706f6ba60Sopenharmony_ci        nbytes += static_cast<std::size_t>(ret);
7806f6ba60Sopenharmony_ci        if (nbytes >= MAX_HHLOG_SIZE) {
7906f6ba60Sopenharmony_ci            return -1;
8006f6ba60Sopenharmony_ci        }
8106f6ba60Sopenharmony_ci        buffer[nbytes++] = '\n';
8206f6ba60Sopenharmony_ci        return buf_->Put(buffer, nbytes);
8306f6ba60Sopenharmony_ci    }
8406f6ba60Sopenharmony_ci
8506f6ba60Sopenharmony_ci    inline int GetLogLevel() const
8606f6ba60Sopenharmony_ci    {
8706f6ba60Sopenharmony_ci        return logLevel_;
8806f6ba60Sopenharmony_ci    }
8906f6ba60Sopenharmony_ci
9006f6ba60Sopenharmony_ci    inline bool IsStopped()
9106f6ba60Sopenharmony_ci    {
9206f6ba60Sopenharmony_ci        return stop_.load();
9306f6ba60Sopenharmony_ci    }
9406f6ba60Sopenharmony_ci
9506f6ba60Sopenharmony_ci    inline void LogSaver()
9606f6ba60Sopenharmony_ci    {
9706f6ba60Sopenharmony_ci        if (logLevel_ == HHLOG_NONE) {
9806f6ba60Sopenharmony_ci            return;
9906f6ba60Sopenharmony_ci        }
10006f6ba60Sopenharmony_ci        logSaver_ = std::thread([this] { this->SaveLog(); });
10106f6ba60Sopenharmony_ci    }
10206f6ba60Sopenharmony_ci
10306f6ba60Sopenharmony_ci    enum SizeConsts:std::size_t {
10406f6ba60Sopenharmony_ci        RING_BUF_SIZE = 4096,
10506f6ba60Sopenharmony_ci        MAX_FORMAT_SIZE = 512,
10606f6ba60Sopenharmony_ci        MAX_HHLOG_SIZE = 1024,
10706f6ba60Sopenharmony_ci    };
10806f6ba60Sopenharmony_ci
10906f6ba60Sopenharmony_ciprivate:
11006f6ba60Sopenharmony_ci    HHLogger() = default;
11106f6ba60Sopenharmony_ci    std::string GetLogFileName() const;
11206f6ba60Sopenharmony_ci    std::string GetFormatTime() const;
11306f6ba60Sopenharmony_ci    int SaveLog();
11406f6ba60Sopenharmony_ci    int InitLogger(const int logLevel, const std::string& logFile);
11506f6ba60Sopenharmony_ci    int UpdateTimer();
11606f6ba60Sopenharmony_ci
11706f6ba60Sopenharmony_ci    int fd_ {-1};
11806f6ba60Sopenharmony_ci    int logLevel_ {HHLOG_NONE};
11906f6ba60Sopenharmony_ci    std::atomic<bool> stop_ {false};
12006f6ba60Sopenharmony_ci    std::atomic<struct timeval> timer_;
12106f6ba60Sopenharmony_ci    std::unique_ptr<RingBuffer> buf_ {nullptr};
12206f6ba60Sopenharmony_ci    std::thread logSaver_;
12306f6ba60Sopenharmony_ci};
12406f6ba60Sopenharmony_ci
12506f6ba60Sopenharmony_ci#define HHLOG(level, expression, format, ...) {                             \
12606f6ba60Sopenharmony_ci    if ((expression) and                                                    \
12706f6ba60Sopenharmony_ci        (!HHLogger::GetInstance().IsStopped()) and                          \
12806f6ba60Sopenharmony_ci        (HHLogger::GetInstance().GetLogLevel() <= HHLOG_##level)) {         \
12906f6ba60Sopenharmony_ci        const char prefix[] {" [" #level "] %s %d %s: %s"};                 \
13006f6ba60Sopenharmony_ci        char buffer[HHLogger::MAX_FORMAT_SIZE];                             \
13106f6ba60Sopenharmony_ci        if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) -1,            \
13206f6ba60Sopenharmony_ci                         prefix, __FILE__, __LINE__, __FUNCTION__, format) < 0) {  \
13306f6ba60Sopenharmony_ci            HHLogger::GetInstance().PutLog("snprintf_s error!");                   \
13406f6ba60Sopenharmony_ci        }                                                                          \
13506f6ba60Sopenharmony_ci        HHLogger::GetInstance().PutLog(buffer, ##__VA_ARGS__);              \
13606f6ba60Sopenharmony_ci    }                                                                       \
13706f6ba60Sopenharmony_ci}
13806f6ba60Sopenharmony_ci
13906f6ba60Sopenharmony_ci#if defined(HH_LOGGER_DEBUG)
14006f6ba60Sopenharmony_ci
14106f6ba60Sopenharmony_ci#define HHLOGD(expression, format, ...) HHLOG(DEBUG, expression, format, ##__VA_ARGS__)
14206f6ba60Sopenharmony_ci#define HHLOGI(expression, format, ...) HHLOG(INFO, expression, format, ##__VA_ARGS__)
14306f6ba60Sopenharmony_ci#define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__)
14406f6ba60Sopenharmony_ci#define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__)
14506f6ba60Sopenharmony_ci#define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
14606f6ba60Sopenharmony_ci
14706f6ba60Sopenharmony_ci#elif defined(HH_LOGGER_INFO)
14806f6ba60Sopenharmony_ci
14906f6ba60Sopenharmony_ci#define HHLOGD(expression, format, ...) {}
15006f6ba60Sopenharmony_ci#define HHLOGI(expression, format, ...) HHLOG(INFO, expression, format, ##__VA_ARGS__)
15106f6ba60Sopenharmony_ci#define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__)
15206f6ba60Sopenharmony_ci#define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__)
15306f6ba60Sopenharmony_ci#define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
15406f6ba60Sopenharmony_ci
15506f6ba60Sopenharmony_ci#elif defined(HH_LOGGER_WARN)
15606f6ba60Sopenharmony_ci
15706f6ba60Sopenharmony_ci#define HHLOGD(expression, format, ...) {}
15806f6ba60Sopenharmony_ci#define HHLOGI(expression, format, ...) {}
15906f6ba60Sopenharmony_ci#define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__)
16006f6ba60Sopenharmony_ci#define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__)
16106f6ba60Sopenharmony_ci#define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
16206f6ba60Sopenharmony_ci
16306f6ba60Sopenharmony_ci#elif defined(HH_LOGGER_ERROR)
16406f6ba60Sopenharmony_ci
16506f6ba60Sopenharmony_ci#define HHLOGD(expression, format, ...) {}
16606f6ba60Sopenharmony_ci#define HHLOGI(expression, format, ...) {}
16706f6ba60Sopenharmony_ci#define HHLOGW(expression, format, ...) {}
16806f6ba60Sopenharmony_ci#define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__)
16906f6ba60Sopenharmony_ci#define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
17006f6ba60Sopenharmony_ci
17106f6ba60Sopenharmony_ci#elif defined(HH_LOGGER_FATAL)
17206f6ba60Sopenharmony_ci
17306f6ba60Sopenharmony_ci#define HHLOGD(expression, format, ...) {}
17406f6ba60Sopenharmony_ci#define HHLOGI(expression, format, ...) {}
17506f6ba60Sopenharmony_ci#define HHLOGW(expression, format, ...) {}
17606f6ba60Sopenharmony_ci#define HHLOGE(expression, format, ...) {}
17706f6ba60Sopenharmony_ci#define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
17806f6ba60Sopenharmony_ci
17906f6ba60Sopenharmony_ci#else
18006f6ba60Sopenharmony_ci
18106f6ba60Sopenharmony_ci#define HHLOGD(expression, format, ...) {}
18206f6ba60Sopenharmony_ci#define HHLOGI(expression, format, ...) {}
18306f6ba60Sopenharmony_ci#define HHLOGW(expression, format, ...) {}
18406f6ba60Sopenharmony_ci#define HHLOGE(expression, format, ...) {}
18506f6ba60Sopenharmony_ci#define HHLOGF(expression, format, ...) {}
18606f6ba60Sopenharmony_ci
18706f6ba60Sopenharmony_ci#endif
18806f6ba60Sopenharmony_ci
18906f6ba60Sopenharmony_ci#define CHECK_NOTNULL(ptr, retval, fmt, ...)                                                                        \
19006f6ba60Sopenharmony_ci    do {                                                                                                            \
19106f6ba60Sopenharmony_ci        if (ptr == nullptr) {                                                                                       \
19206f6ba60Sopenharmony_ci            HHLOGE(true, "CHECK_NOTNULL(%s) in %s:%d FAILED, " fmt, #ptr, __func__, \
19306f6ba60Sopenharmony_ci                       __LINE__, ##__VA_ARGS__);                                                                    \
19406f6ba60Sopenharmony_ci            return retval;                                                                                          \
19506f6ba60Sopenharmony_ci        }                                                                                                           \
19606f6ba60Sopenharmony_ci    } while (0)
19706f6ba60Sopenharmony_ci
19806f6ba60Sopenharmony_ci#define CHECK_TRUE(expr, retval, fmt, ...)                                                                          \
19906f6ba60Sopenharmony_ci    do {                                                                                                            \
20006f6ba60Sopenharmony_ci        if (!(expr)) {                                                                                              \
20106f6ba60Sopenharmony_ci            HHLOGE(true, "CHECK_TRUE(%s) in %s:%d FAILED, " fmt, #expr, __func__, __LINE__, ##__VA_ARGS__);     \
20206f6ba60Sopenharmony_ci            return retval;                                                                                          \
20306f6ba60Sopenharmony_ci        }                                                                                                           \
20406f6ba60Sopenharmony_ci    } while (0)
20506f6ba60Sopenharmony_ci
20606f6ba60Sopenharmony_ci#endif  // HHLOG_H