1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. 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 26static constexpr int FILE_MODE = 0644; 27 28std::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 43int 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 57int 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 87std::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}