Coverage Report

Created: 2025-05-22 17:46

/root/doris/cloud/src/common/logging.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 "logging.h"
19
20
#include <bthread/bthread.h>
21
#include <bthread/types.h>
22
#include <glog/logging.h>
23
#include <glog/vlog_is_on.h>
24
25
#include <iomanip>
26
#include <iostream>
27
#include <mutex>
28
29
#include "config.h"
30
31
namespace doris::cloud {
32
33
8.59k
static butil::LinkedList<AnnotateTag>* get_annotate_tag_list() {
34
8.59k
    static std::once_flag log_annotated_tags_key_once;
35
8.59k
    static bthread_key_t log_annotated_tags_key;
36
8.59k
    std::call_once(
37
8.59k
            log_annotated_tags_key_once,
38
8.59k
            +[](bthread_key_t* key) {
39
9
                bthread_key_create(
40
87
                        key, +[](void* value) {
41
87
                            delete reinterpret_cast<butil::LinkedList<AnnotateTag>*>(value);
42
87
                        });
43
9
            },
44
8.59k
            &log_annotated_tags_key);
45
46
8.59k
    auto* tag_list = reinterpret_cast<butil::LinkedList<AnnotateTag>*>(
47
8.59k
            bthread_getspecific(log_annotated_tags_key));
48
8.59k
    if (!tag_list) {
49
152
        tag_list = new butil::LinkedList<AnnotateTag>();
50
152
        bthread_setspecific(log_annotated_tags_key, tag_list);
51
152
    }
52
8.59k
    return tag_list;
53
8.59k
}
54
55
AnnotateTag::AnnotateTag(default_tag_t, std::string_view key, std::string value)
56
30
        : key_(key), value_(std::move(value)) {
57
30
    get_annotate_tag_list()->Append(this);
58
30
}
59
60
AnnotateTag::AnnotateTag(std::string_view key, std::string_view value)
61
18
        : AnnotateTag(default_tag, key, fmt::format("\"{}\"", value)) {}
62
63
30
AnnotateTag::~AnnotateTag() {
64
30
    RemoveFromList();
65
30
}
66
67
8.56k
void AnnotateTag::format_tag_list(std::ostream& stream) {
68
8.56k
    butil::LinkedList<AnnotateTag>* list = get_annotate_tag_list();
69
8.56k
    butil::LinkNode<AnnotateTag>* head = list->head();
70
8.56k
    const butil::LinkNode<AnnotateTag>* end = list->end();
71
8.58k
    for (; head != end; head = head->next()) {
72
21
        stream << ' ' << head->value()->key_ << '=' << head->value()->value_;
73
21
    }
74
8.56k
}
75
76
0
void custom_prefix(std::ostream& s, const google::LogMessageInfo& l, void*) {
77
    // Add prefix "RuntimeLogger ".
78
0
    s << "RuntimeLogger ";
79
    // Same as in fe.log
80
    // The following is same as default log format. eg:
81
    // I20240605 15:25:15.677153 1763151 meta_service_txn.cpp:481] msg...
82
0
    s << l.severity[0];
83
0
    s << std::setw(4) << 1900 + l.time.year();
84
0
    s << std::setw(2) << 1 + l.time.month();
85
0
    s << std::setw(2) << l.time.day();
86
0
    s << ' ';
87
0
    s << std::setw(2) << l.time.hour() << ':';
88
0
    s << std::setw(2) << l.time.min() << ':';
89
0
    s << std::setw(2) << l.time.sec() << ".";
90
0
    s << std::setw(6) << l.time.usec();
91
0
    s << ' ';
92
0
    s << std::setfill(' ') << std::setw(5);
93
0
    s << l.thread_id << std::setfill('0');
94
0
    s << ' ';
95
0
    s << l.filename << ':' << l.line_number << "]";
96
0
}
97
98
/**
99
 * @param basename the basename of log file
100
 * @return true for success
101
 */
102
13
bool init_glog(const char* basename) {
103
13
    static std::mutex mtx;
104
13
    static bool inited = false;
105
13
    std::lock_guard<std::mutex> logging_lock(mtx);
106
13
    if (inited) return true;
107
108
13
    bool log_to_console = (getenv("DORIS_LOG_TO_STDERR") != nullptr);
109
13
    if (log_to_console) {
110
0
        if (config::enable_file_logger) {
111
0
            FLAGS_alsologtostderr = true;
112
0
        } else {
113
0
            FLAGS_logtostderr = true;
114
0
        }
115
13
    } else {
116
13
        FLAGS_alsologtostderr = false;
117
        // Don't log to stderr except fatal level
118
        // so fatal log can output to be.out .
119
13
        FLAGS_stderrthreshold = google::ERROR;
120
13
    }
121
122
    // Set glog log dir
123
13
    FLAGS_log_dir = config::log_dir;
124
    // Buffer log messages for at most this many seconds
125
13
    FLAGS_logbufsecs = 1;
126
    // Set log roll mode
127
    // Candidates: day, hour, size
128
13
    FLAGS_log_split_method = "size";
129
    // Sets the maximum log file size (in MB).
130
13
    FLAGS_max_log_size = config::log_size_mb;
131
    // Set roll num
132
13
    FLAGS_log_filenum_quota = config::log_filenum_quota;
133
134
13
#ifdef GLOG_HAS_WARN_LOG_FILENUM_QUOTA
135
    // Set warn log roll num
136
13
    FLAGS_warn_log_filenum_quota = config::warn_log_filenum_quota;
137
13
#endif
138
139
    // clang-format off
140
    // set log level
141
13
    std::string& loglevel = config::log_level;
142
    // Can be 0 1 2 3 ... the larger the higher level for logging,
143
    // corrensponding to INFO WARNING ERROR FATAL
144
    // const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3, NUM_SEVERITIES = 4;
145
44
    auto tolower = [](std::string s) { for (auto& i : s) i |= 0x20; return s; };
146
13
    FLAGS_minloglevel = tolower(loglevel) == "info"  ? 0
147
13
                      : tolower(loglevel) == "warn"  ? 1
148
2
                      : tolower(loglevel) == "error" ? 2
149
2
                      : tolower(loglevel) == "fatal" ? 3
150
2
                      :                                0; // Default INFO
151
    // clang-format on
152
153
    // Log messages at a level <= this flag are buffered.
154
    // Log messages at a higher level are flushed immediately.
155
13
    FLAGS_logbuflevel = config::log_immediate_flush ? -1 : 0;
156
157
    // Set verbose modules
158
13
    FLAGS_v = -1;
159
13
    for (auto& i : config::log_verbose_modules) {
160
0
        if (i.empty()) continue;
161
0
        google::SetVLOGLevel(i.c_str(), config::log_verbose_level);
162
0
    }
163
13
    if (log_to_console) {
164
        // Only add prefix if log output to stderr
165
0
        google::InitGoogleLogging(basename, &custom_prefix);
166
13
    } else {
167
13
        google::InitGoogleLogging(basename);
168
13
    }
169
13
    inited = true;
170
13
    return true;
171
13
}
172
173
} // namespace doris::cloud