1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2026
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/Logging.h"
#include "td/telegram/ConfigManager.h"
#include "td/telegram/FileReferenceManager.h"
#include "td/telegram/files/FileGcWorker.h"
#include "td/telegram/files/FileLoaderUtils.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/net/ConnectionCreator.h"
#include "td/telegram/net/DcAuthManager.h"
#include "td/telegram/net/NetQuery.h"
#include "td/telegram/NotificationManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/UpdatesManager.h"
#include "td/mtproto/SessionConnection.h"
#include "td/mtproto/Transport.h"
#include "td/db/binlog/Binlog.h"
#include "td/db/SqliteStatement.h"
#include "td/net/GetHostByNameActor.h"
#include "td/net/TransparentProxy.h"
#include "td/actor/actor.h"
#include "td/utils/algorithm.h"
#include "td/utils/ExitGuard.h"
#include "td/utils/FileLog.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/NullLog.h"
#include "td/utils/port/detail/NativeFd.h"
#include "td/utils/TsLog.h"
#include <atomic>
#include <map>
#include <mutex>
namespace td {
static std::mutex logging_mutex;
static FileLog file_log;
static TsLog ts_log(&file_log);
static NullLog null_log;
static ExitGuard exit_guard;
#define ADD_TAG(tag) \
{ #tag, &VERBOSITY_NAME(tag) }
static const std::map<Slice, int *> log_tags{
ADD_TAG(td_init), ADD_TAG(update_file), ADD_TAG(connections), ADD_TAG(binlog),
ADD_TAG(proxy), ADD_TAG(net_query), ADD_TAG(td_requests), ADD_TAG(dc),
ADD_TAG(file_loader), ADD_TAG(mtproto), ADD_TAG(raw_mtproto), ADD_TAG(fd),
ADD_TAG(actor), ADD_TAG(sqlite), ADD_TAG(notifications), ADD_TAG(get_difference),
ADD_TAG(file_gc), ADD_TAG(config_recoverer), ADD_TAG(dns_resolver), ADD_TAG(file_references)};
#undef ADD_TAG
Status Logging::set_current_stream(td_api::object_ptr<td_api::LogStream> stream) {
if (stream == nullptr) {
return Status::Error("Log stream must be non-empty");
}
std::lock_guard<std::mutex> lock(logging_mutex);
switch (stream->get_id()) {
case td_api::logStreamDefault::ID:
log_interface = default_log_interface;
return Status::OK();
case td_api::logStreamFile::ID: {
auto file_stream = td_api::move_object_as<td_api::logStreamFile>(stream);
auto max_log_file_size = file_stream->max_file_size_;
if (max_log_file_size <= 0) {
return Status::Error("Max log file size must be positive");
}
auto redirect_stderr = file_stream->redirect_stderr_;
TRY_STATUS(file_log.init(file_stream->path_, max_log_file_size, redirect_stderr));
std::atomic_thread_fence(std::memory_order_release); // better than nothing
log_interface = &ts_log;
return Status::OK();
}
case td_api::logStreamEmpty::ID:
log_interface = &null_log;
return Status::OK();
default:
UNREACHABLE();
return Status::OK();
}
}
Result<td_api::object_ptr<td_api::LogStream>> Logging::get_current_stream() {
std::lock_guard<std::mutex> lock(logging_mutex);
if (log_interface == default_log_interface) {
return td_api::make_object<td_api::logStreamDefault>();
}
if (log_interface == &null_log) {
return td_api::make_object<td_api::logStreamEmpty>();
}
if (log_interface == &ts_log) {
return td_api::make_object<td_api::logStreamFile>(file_log.get_path().str(), file_log.get_rotate_threshold(),
file_log.get_redirect_stderr());
}
return Status::Error("Log stream is unrecognized");
}
Status Logging::set_verbosity_level(int new_verbosity_level) {
std::lock_guard<std::mutex> lock(logging_mutex);
if (0 <= new_verbosity_level && new_verbosity_level <= VERBOSITY_NAME(NEVER)) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(FATAL) + new_verbosity_level);
return Status::OK();
}
return Status::Error("Wrong new verbosity level specified");
}
int Logging::get_verbosity_level() {
std::lock_guard<std::mutex> lock(logging_mutex);
return GET_VERBOSITY_LEVEL();
}
vector<string> Logging::get_tags() {
return transform(log_tags, [](auto &tag) { return tag.first.str(); });
}
Status Logging::set_tag_verbosity_level(Slice tag, int new_verbosity_level) {
if (tag.empty()) {
return Status::Error("Log tag must be non-empty");
}
auto it = log_tags.find(tag);
if (it == log_tags.end()) {
return Status::Error("Log tag is not found");
}
std::lock_guard<std::mutex> lock(logging_mutex);
*it->second = clamp(new_verbosity_level, 1, VERBOSITY_NAME(NEVER));
return Status::OK();
}
Result<int> Logging::get_tag_verbosity_level(Slice tag) {
if (tag.empty()) {
return Status::Error("Log tag must be non-empty");
}
auto it = log_tags.find(tag);
if (it == log_tags.end()) {
return Status::Error("Log tag is not found");
}
std::lock_guard<std::mutex> lock(logging_mutex);
return *it->second;
}
void Logging::add_message(int log_verbosity_level, Slice message) {
int VERBOSITY_NAME(client) = clamp(log_verbosity_level, 0, VERBOSITY_NAME(NEVER));
VLOG(client) << message;
}
} // namespace td
|