Coverage Report

Created: 2025-11-20 04:52

/root/doris/be/src/common/logconfig.cpp
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include <ctype.h>
19
#include <stdint.h>
20
21
#include <cerrno>
22
#include <cstdlib>
23
#include <cstring>
24
#include <iomanip>
25
#include <iostream>
26
#include <mutex>
27
#include <string>
28
#include <vector>
29
30
#include "common/config.h"
31
#include "common/logging.h"
32
33
namespace doris {
34
35
static bool logging_initialized = false;
36
37
static std::mutex logging_mutex;
38
39
// Implement the custom log format: I20250118 10:53:06.239614 1318521 timezone_utils.cpp:115] Preloaded653 timezones.
40
struct StdoutLogSink : google::LogSink {
41
    void send(google::LogSeverity severity, const char* /*full_filename*/,
42
              const char* base_filename, int line, const google::LogMessageTime& time,
43
0
              const char* message, std::size_t message_len) override {
44
        // 1.  Convert log severity to corresponding character (I/W/E/F)
45
0
        char severity_char;
46
0
        switch (severity) {
47
0
        case google::GLOG_INFO:
  Branch (47:9): [True: 0, False: 0]
48
0
            severity_char = 'I';
49
0
            break;
50
0
        case google::GLOG_WARNING:
  Branch (50:9): [True: 0, False: 0]
51
0
            severity_char = 'W';
52
0
            break;
53
0
        case google::GLOG_ERROR:
  Branch (53:9): [True: 0, False: 0]
54
0
            severity_char = 'E';
55
0
            break;
56
0
        case google::GLOG_FATAL:
  Branch (56:9): [True: 0, False: 0]
57
0
            severity_char = 'F';
58
0
            break;
59
0
        default:
  Branch (59:9): [True: 0, False: 0]
60
0
            severity_char = '?';
61
0
            break;
62
0
        }
63
        // Set output formatting flags
64
0
        std::cout << std::setfill('0');
65
66
        // 1. Log severity (I/W/E/F)
67
0
        std::cout << severity_char;
68
69
        // 2. Date (YYYYMMDD)
70
        // Note: tm_year is years since 1900, tm_mon is 0-based (0-11)
71
0
        std::cout << std::setw(4) << (time.year() + 1900) << std::setw(2) << std::setfill('0')
72
0
                  << (time.month() + 1) << std::setw(2) << std::setfill('0') << time.day();
73
74
        // 3. Time (HH:MM:SS.ffffff)
75
0
        std::cout << " " << std::setw(2) << std::setfill('0') << time.hour() << ":" << std::setw(2)
76
0
                  << std::setfill('0') << time.min() << ":" << std::setw(2) << std::setfill('0')
77
0
                  << time.sec() << "." << std::setw(6) << std::setfill('0') << time.usec();
78
79
        // 4. Process ID
80
0
        std::cout << " " << getpid();
81
82
        // 5. Filename and line number
83
0
        std::cout << " " << base_filename << ":" << line << "] ";
84
85
        // 6. Log message
86
0
        std::cout.write(message, message_len);
87
88
        // Add newline and flush
89
0
        std::cout << std::endl;
90
0
    }
91
};
92
93
static StdoutLogSink stdout_log_sink;
94
95
3
static bool iequals(const std::string& a, const std::string& b) {
96
3
    unsigned int sz = a.size();
97
3
    if (b.size() != sz) {
  Branch (97:9): [True: 2, False: 1]
98
2
        return false;
99
2
    }
100
5
    for (unsigned int i = 0; i < sz; ++i) {
  Branch (100:30): [True: 4, False: 1]
101
4
        if (tolower(a[i]) != tolower(b[i])) {
  Branch (101:13): [True: 0, False: 4]
102
0
            return false;
103
0
        }
104
4
    }
105
1
    return true;
106
1
}
107
108
// if custom_date_time_format = false, same format as in be.log
109
// The following is same as default log format. eg:
110
// I20240605 15:25:15.677153 1763151 wal_manager.cpp:481] msg...
111
template <bool add_runtime_logger_prefix = false, bool custom_date_time_format = false>
112
0
void custom_prefix(std::ostream& s, const google::LogMessageInfo& l, void* arg) {
113
0
    if constexpr (add_runtime_logger_prefix) {
  Branch (113:19): [Folded - Ignored]
  Branch (113:19): [Folded - Ignored]
  Branch (113:19): [Folded - Ignored]
114
        // Add prefix "RuntimeLogger ".
115
0
        s << "RuntimeLogger ";
116
0
    }
117
0
    s << l.severity[0];
118
119
    // Add a space if custom_date_time_format.
120
0
    if constexpr (custom_date_time_format) {
  Branch (120:19): [Folded - Ignored]
  Branch (120:19): [Folded - Ignored]
  Branch (120:19): [Folded - Ignored]
121
0
        s << ' ';
122
0
    }
123
124
0
    std::tm tm_time = {};
125
0
    tm_time.tm_year = l.time.year();
126
0
    tm_time.tm_mon = l.time.month();
127
0
    tm_time.tm_mday = l.time.day();
128
0
    tm_time.tm_hour = l.time.hour();
129
0
    tm_time.tm_min = l.time.min();
130
0
    tm_time.tm_sec = l.time.sec();
131
132
0
    if constexpr (custom_date_time_format) {
  Branch (132:19): [Folded - Ignored]
  Branch (132:19): [Folded - Ignored]
  Branch (132:19): [Folded - Ignored]
133
0
        s << std::put_time(&tm_time, config::sys_log_custom_date_time_format.c_str());
134
0
        if (!config::sys_log_custom_date_time_ms_format.empty()) {
  Branch (134:13): [True: 0, False: 0]
  Branch (134:13): [True: 0, False: 0]
135
0
            s << fmt::format(config::sys_log_custom_date_time_ms_format, l.time.usec() / 1000);
136
0
        }
137
0
    } else {
138
0
        s << std::put_time(&tm_time, "%Y%m%d %H:%M:%S");
139
0
        s << "." << std::setw(6) << l.time.usec();
140
0
    }
141
142
0
    s << ' ';
143
0
    s << std::setfill(' ') << std::setw(5);
144
0
    s << l.thread_id << std::setfill('0');
145
0
    s << ' ';
146
0
    s << l.filename << ':' << l.line_number << "]";
147
0
}
Unexecuted instantiation: _ZN5doris13custom_prefixILb1ELb1EEEvRSoRKN6google14LogMessageInfoEPv
Unexecuted instantiation: _ZN5doris13custom_prefixILb1ELb0EEEvRSoRKN6google14LogMessageInfoEPv
Unexecuted instantiation: _ZN5doris13custom_prefixILb0ELb1EEEvRSoRKN6google14LogMessageInfoEPv
148
149
1
bool init_glog(const char* basename) {
150
1
    std::lock_guard<std::mutex> logging_lock(logging_mutex);
151
152
1
    if (logging_initialized) {
  Branch (152:9): [True: 0, False: 1]
153
0
        return true;
154
0
    }
155
156
1
    bool log_to_console = (getenv("DORIS_LOG_TO_STDERR") != nullptr);
157
1
    if (log_to_console) {
  Branch (157:9): [True: 0, False: 1]
158
0
        if (doris::config::enable_file_logger) {
  Branch (158:13): [True: 0, False: 0]
159
            // will output log to be.info and output log to stdout
160
0
            google::AddLogSink(&stdout_log_sink);
161
0
        } else {
162
            // enable_file_logger is false, will only output log to stdout
163
            // Not output to stderr because be.out will output log to stderr
164
0
            FLAGS_logtostdout = true;
165
0
        }
166
0
    }
167
168
    // don't log to stderr except fatal level
169
    // so fatal log can output to be.out .
170
1
    FLAGS_stderrthreshold = google::FATAL;
171
    // set glog log dir
172
    // ATTN: sys_log_dir is deprecated, this is just for compatibility
173
1
    std::string log_dir = config::sys_log_dir;
174
1
    if (log_dir == "") {
  Branch (174:9): [True: 1, False: 0]
175
1
        log_dir = getenv("LOG_DIR");
176
1
    }
177
1
    FLAGS_log_dir = log_dir;
178
    // 0 means buffer INFO only
179
1
    FLAGS_logbuflevel = 0;
180
    // buffer log messages for at most this many seconds
181
1
    FLAGS_logbufsecs = 30;
182
    // set roll num
183
1
    FLAGS_log_filenum_quota = config::sys_log_roll_num;
184
185
    // set log level
186
1
    std::string& loglevel = config::sys_log_level;
187
1
    if (iequals(loglevel, "INFO")) {
  Branch (187:9): [True: 1, False: 0]
188
1
        FLAGS_minloglevel = 0;
189
1
    } else if (iequals(loglevel, "WARNING")) {
  Branch (189:16): [True: 0, False: 0]
190
0
        FLAGS_minloglevel = 1;
191
0
    } else if (iequals(loglevel, "ERROR")) {
  Branch (191:16): [True: 0, False: 0]
192
0
        FLAGS_minloglevel = 2;
193
0
    } else if (iequals(loglevel, "FATAL")) {
  Branch (193:16): [True: 0, False: 0]
194
0
        FLAGS_minloglevel = 3;
195
0
    } else {
196
0
        std::cerr << "sys_log_level needs to be INFO, WARNING, ERROR, FATAL" << std::endl;
197
0
        return false;
198
0
    }
199
200
    // set log buffer level
201
    // default is 0
202
1
    std::string& logbuflevel = config::log_buffer_level;
203
1
    if (iequals(logbuflevel, "-1")) {
  Branch (203:9): [True: 0, False: 1]
204
0
        FLAGS_logbuflevel = -1;
205
1
    } else if (iequals(logbuflevel, "0")) {
  Branch (205:16): [True: 0, False: 1]
206
0
        FLAGS_logbuflevel = 0;
207
0
    }
208
209
    // set log roll mode
210
1
    std::string& rollmode = config::sys_log_roll_mode;
211
1
    std::string sizeflag = "SIZE-MB-";
212
1
    bool ok = false;
213
1
    if (rollmode.compare("TIME-DAY") == 0) {
  Branch (213:9): [True: 0, False: 1]
214
0
        FLAGS_log_split_method = "day";
215
0
        ok = true;
216
1
    } else if (rollmode.compare("TIME-HOUR") == 0) {
  Branch (216:16): [True: 0, False: 1]
217
0
        FLAGS_log_split_method = "hour";
218
0
        ok = true;
219
1
    } else if (rollmode.substr(0, sizeflag.length()).compare(sizeflag) == 0) {
  Branch (219:16): [True: 1, False: 0]
220
1
        FLAGS_log_split_method = "size";
221
1
        std::string sizestr = rollmode.substr(sizeflag.size(), rollmode.size() - sizeflag.size());
222
1
        if (sizestr.size() != 0) {
  Branch (222:13): [True: 1, False: 0]
223
1
            char* end = nullptr;
224
1
            errno = 0;
225
1
            const char* sizecstr = sizestr.c_str();
226
1
            int64_t ret64 = strtoll(sizecstr, &end, 10);
227
1
            if ((errno == 0) && (end == sizecstr + strlen(sizecstr))) {
  Branch (227:17): [True: 1, False: 0]
  Branch (227:33): [True: 1, False: 0]
228
1
                int32_t retval = static_cast<int32_t>(ret64);
229
1
                if (retval == ret64) {
  Branch (229:21): [True: 1, False: 0]
230
1
                    FLAGS_max_log_size = retval;
231
1
                    ok = true;
232
1
                }
233
1
            }
234
1
        }
235
1
    } else {
236
0
        ok = false;
237
0
    }
238
1
    if (!ok) {
  Branch (238:9): [True: 0, False: 1]
239
0
        std::cerr << "sys_log_roll_mode needs to be TIME-DAY, TIME-HOUR, SIZE-MB-nnn" << std::endl;
240
0
        return false;
241
0
    }
242
243
    // set verbose modules.
244
1
    FLAGS_v = config::sys_log_verbose_flags_v;
245
1
    std::vector<std::string>& verbose_modules = config::sys_log_verbose_modules;
246
1
    int32_t vlog_level = config::sys_log_verbose_level;
247
1
    for (size_t i = 0; i < verbose_modules.size(); i++) {
  Branch (247:24): [True: 0, False: 1]
248
0
        if (verbose_modules[i].size() != 0) {
  Branch (248:13): [True: 0, False: 0]
249
0
            google::SetVLOGLevel(verbose_modules[i].c_str(), vlog_level);
250
0
        }
251
0
    }
252
253
1
    if (log_to_console) {
  Branch (253:9): [True: 0, False: 1]
254
        // Add prefix if log output to stderr
255
0
        if (config::sys_log_enable_custom_date_time_format) {
  Branch (255:13): [True: 0, False: 0]
256
0
            google::InitGoogleLogging(basename, &custom_prefix<true, true>);
257
0
        } else {
258
0
            google::InitGoogleLogging(basename, &custom_prefix<true, false>);
259
0
        }
260
1
    } else {
261
1
        if (config::sys_log_enable_custom_date_time_format) {
  Branch (261:13): [True: 0, False: 1]
262
0
            google::InitGoogleLogging(basename, &custom_prefix<false, true>);
263
1
        } else {
264
1
            google::InitGoogleLogging(basename);
265
1
        }
266
1
    }
267
268
1
    logging_initialized = true;
269
270
1
    return true;
271
1
}
272
273
0
void shutdown_logging() {
274
0
    std::lock_guard<std::mutex> logging_lock(logging_mutex);
275
0
    google::RemoveLogSink(&stdout_log_sink);
276
0
    google::ShutdownGoogleLogging();
277
0
}
278
279
0
void update_logging(const std::string& name, const std::string& value) {
280
0
    if ("sys_log_level" == name) {
  Branch (280:9): [True: 0, False: 0]
281
0
        if (iequals(value, "INFO")) {
  Branch (281:13): [True: 0, False: 0]
282
0
            FLAGS_minloglevel = 0;
283
0
        } else if (iequals(value, "WARNING")) {
  Branch (283:20): [True: 0, False: 0]
284
0
            FLAGS_minloglevel = 1;
285
0
        } else if (iequals(value, "ERROR")) {
  Branch (285:20): [True: 0, False: 0]
286
0
            FLAGS_minloglevel = 2;
287
0
        } else if (iequals(value, "FATAL")) {
  Branch (287:20): [True: 0, False: 0]
288
0
            FLAGS_minloglevel = 3;
289
0
        } else {
290
0
            LOG(WARNING) << "update sys_log_level failed, need to be INFO, WARNING, ERROR, FATAL";
291
0
        }
292
0
    }
293
0
}
294
295
} // namespace doris