Coverage Report

Created: 2025-10-30 09:08

/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:
48
0
            severity_char = 'I';
49
0
            break;
50
0
        case google::GLOG_WARNING:
51
0
            severity_char = 'W';
52
0
            break;
53
0
        case google::GLOG_ERROR:
54
0
            severity_char = 'E';
55
0
            break;
56
0
        case google::GLOG_FATAL:
57
0
            severity_char = 'F';
58
0
            break;
59
0
        default:
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
18
static bool iequals(const std::string& a, const std::string& b) {
96
18
    unsigned int sz = a.size();
97
18
    if (b.size() != sz) {
98
4
        return false;
99
4
    }
100
58
    for (unsigned int i = 0; i < sz; ++i) {
101
44
        if (tolower(a[i]) != tolower(b[i])) {
102
0
            return false;
103
0
        }
104
44
    }
105
14
    return true;
106
14
}
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) {
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) {
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) {
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()) {
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
8
bool init_glog(const char* basename) {
150
8
    std::lock_guard<std::mutex> logging_lock(logging_mutex);
151
152
8
    if (logging_initialized) {
153
0
        return true;
154
0
    }
155
156
8
    bool log_to_console = (getenv("DORIS_LOG_TO_STDERR") != nullptr);
157
8
    if (log_to_console) {
158
0
        if (doris::config::enable_file_logger) {
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
8
    FLAGS_stderrthreshold = google::FATAL;
171
    // set glog log dir
172
    // ATTN: sys_log_dir is deprecated, this is just for compatibility
173
8
    std::string log_dir = config::sys_log_dir;
174
8
    if (log_dir == "") {
175
8
        log_dir = getenv("LOG_DIR");
176
8
    }
177
8
    FLAGS_log_dir = log_dir;
178
    // 0 means buffer INFO only
179
8
    FLAGS_logbuflevel = 0;
180
    // buffer log messages for at most this many seconds
181
8
    FLAGS_logbufsecs = 30;
182
    // set roll num
183
8
    FLAGS_log_filenum_quota = config::sys_log_roll_num;
184
185
    // set log level
186
8
    std::string& loglevel = config::sys_log_level;
187
8
    if (iequals(loglevel, "INFO")) {
188
8
        FLAGS_minloglevel = 0;
189
8
    } else if (iequals(loglevel, "WARNING")) {
190
0
        FLAGS_minloglevel = 1;
191
0
    } else if (iequals(loglevel, "ERROR")) {
192
0
        FLAGS_minloglevel = 2;
193
0
    } else if (iequals(loglevel, "FATAL")) {
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
8
    std::string& logbuflevel = config::log_buffer_level;
203
8
    if (iequals(logbuflevel, "-1")) {
204
6
        FLAGS_logbuflevel = -1;
205
6
    } else if (iequals(logbuflevel, "0")) {
206
0
        FLAGS_logbuflevel = 0;
207
0
    }
208
209
    // set log roll mode
210
8
    std::string& rollmode = config::sys_log_roll_mode;
211
8
    std::string sizeflag = "SIZE-MB-";
212
8
    bool ok = false;
213
8
    if (rollmode.compare("TIME-DAY") == 0) {
214
0
        FLAGS_log_split_method = "day";
215
0
        ok = true;
216
8
    } else if (rollmode.compare("TIME-HOUR") == 0) {
217
0
        FLAGS_log_split_method = "hour";
218
0
        ok = true;
219
8
    } else if (rollmode.substr(0, sizeflag.length()).compare(sizeflag) == 0) {
220
8
        FLAGS_log_split_method = "size";
221
8
        std::string sizestr = rollmode.substr(sizeflag.size(), rollmode.size() - sizeflag.size());
222
8
        if (sizestr.size() != 0) {
223
8
            char* end = nullptr;
224
8
            errno = 0;
225
8
            const char* sizecstr = sizestr.c_str();
226
8
            int64_t ret64 = strtoll(sizecstr, &end, 10);
227
8
            if ((errno == 0) && (end == sizecstr + strlen(sizecstr))) {
228
8
                int32_t retval = static_cast<int32_t>(ret64);
229
8
                if (retval == ret64) {
230
8
                    FLAGS_max_log_size = retval;
231
8
                    ok = true;
232
8
                }
233
8
            }
234
8
        }
235
8
    } else {
236
0
        ok = false;
237
0
    }
238
8
    if (!ok) {
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
8
    FLAGS_v = config::sys_log_verbose_flags_v;
245
8
    std::vector<std::string>& verbose_modules = config::sys_log_verbose_modules;
246
8
    int32_t vlog_level = config::sys_log_verbose_level;
247
18
    for (size_t i = 0; i < verbose_modules.size(); i++) {
248
10
        if (verbose_modules[i].size() != 0) {
249
10
            google::SetVLOGLevel(verbose_modules[i].c_str(), vlog_level);
250
10
        }
251
10
    }
252
253
8
    if (log_to_console) {
254
        // Add prefix if log output to stderr
255
0
        if (config::sys_log_enable_custom_date_time_format) {
256
0
            google::InitGoogleLogging(basename, &custom_prefix<true, true>);
257
0
        } else {
258
0
            google::InitGoogleLogging(basename, &custom_prefix<true, false>);
259
0
        }
260
8
    } else {
261
8
        if (config::sys_log_enable_custom_date_time_format) {
262
0
            google::InitGoogleLogging(basename, &custom_prefix<false, true>);
263
8
        } else {
264
8
            google::InitGoogleLogging(basename);
265
8
        }
266
8
    }
267
268
8
    logging_initialized = true;
269
270
8
    return true;
271
8
}
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) {
281
0
        if (iequals(value, "INFO")) {
282
0
            FLAGS_minloglevel = 0;
283
0
        } else if (iequals(value, "WARNING")) {
284
0
            FLAGS_minloglevel = 1;
285
0
        } else if (iequals(value, "ERROR")) {
286
0
            FLAGS_minloglevel = 2;
287
0
        } else if (iequals(value, "FATAL")) {
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