1 /*
2 * Copyright (c) 2022 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 #include <cstdio>
17 #include <ctime>
18 #include <sstream>
19
20 #include <sys/time.h>
21
22
23 #include "libbpf_logger.h"
24 #include "hhlog.h"
25
26 static constexpr int FILE_MODE = 0644;
27
MakeUnique(const std::string & logFile,int logLevel)28 std::unique_ptr<LIBBPFLogger> LIBBPFLogger::MakeUnique(const std::string& logFile, int logLevel)
29 {
30 std::unique_ptr<LIBBPFLogger> logger {new(std::nothrow) LIBBPFLogger {logLevel}};
31 if (logger == nullptr) {
32 return nullptr;
33 }
34 #if defined(BPF_LOGGER_DEBUG) || defined(BPF_LOGGER_INFO) || defined(BPF_LOGGER_WARN) || \
35 defined(BPF_LOGGER_ERROR) || defined(BPF_LOGGER_FATAL)
36 if (logger->OpenLogFile(logFile) != 0) {
37 return nullptr;
38 }
39 #endif
40 return logger;
41 }
42
Printf(int logLevel,const char * format,va_list args)43 int LIBBPFLogger::Printf(int logLevel, const char* format, va_list args)
44 {
45 HHLOGI(true, "current libbpf log level = %d, target level = %d", logLevel, logLevel_);
46 if (logLevel > logLevel_) {
47 return 0;
48 }
49 #if defined(BPF_LOGGER_DEBUG) || defined(BPF_LOGGER_INFO) || defined(BPF_LOGGER_WARN) || \
50 defined(BPF_LOGGER_ERROR) || defined(BPF_LOGGER_FATAL)
51 return vdprintf(fd_, format, args);
52 #else
53 return 0;
54 #endif
55 }
56
OpenLogFile(const std::string & logFile)57 int LIBBPFLogger::OpenLogFile(const std::string& logFile)
58 {
59 if (logFile.compare("stdout") == 0) {
60 if (fcntl(STDOUT_FILENO, F_GETFL)) {
61 fd_ = open("/dev/stdout", O_WRONLY);
62 } else {
63 fd_ = STDOUT_FILENO;
64 }
65 if (fd_ < 0) {
66 return -1;
67 }
68 return 0;
69 }
70 auto fileName = GetLogFileName();
71 if (fileName.length() == 0) {
72 return -1;
73 }
74 fileName = "/data/local/tmp/" + fileName;
75 fd_ = open(fileName.c_str(), O_WRONLY | O_CREAT, FILE_MODE);
76 if (fd_ < 0) {
77 return -1;
78 }
79 unlink(logFile.c_str());
80 if (link(fileName.c_str(), logFile.c_str()) != 0) {
81 return -1;
82 }
83
84 return 0;
85 }
86
GetLogFileName() const87 std::string LIBBPFLogger::GetLogFileName() const
88 {
89 struct timeval timer;
90 gettimeofday(&timer, nullptr);
91 time_t now = (time_t) timer.tv_sec;
92 struct tm* tmPtr {nullptr};
93 tmPtr = localtime(&now);
94 CHECK_NOTNULL(tmPtr, "", "GetLogFileName fail");
95 std::stringstream ss;
96 constexpr int yearStart {1900};
97 constexpr int monthStart {1};
98 ss << std::to_string(tmPtr->tm_year + yearStart) << ".";
99 ss << std::to_string(tmPtr->tm_mon + monthStart) << ".";
100 ss << std::to_string(tmPtr->tm_mday) << "_";
101 ss << std::to_string(tmPtr->tm_hour) << ".";
102 ss << std::to_string(tmPtr->tm_min) << ".";
103 ss << std::to_string(tmPtr->tm_sec) << ".libbpf.log";
104 return ss.str();
105 }