blob: a4aea28805f9f839ea9268c4e1b359cc18027316 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#if defined(WEBRTC_WIN)
henrike@webrtc.orgf0488722014-05-13 18:00:2612#include <windows.h>
conceptgenesis3f705622016-01-30 22:40:4413#if _MSC_VER < 1900
henrike@webrtc.orgf0488722014-05-13 18:00:2614#define snprintf _snprintf
conceptgenesis3f705622016-01-30 22:40:4415#endif
henrike@webrtc.orgf0488722014-05-13 18:00:2616#undef ERROR // wingdi.h
17#endif
18
19#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
20#include <CoreServices/CoreServices.h>
21#elif defined(WEBRTC_ANDROID)
22#include <android/log.h>
Yves Gerey988cc082018-10-23 10:03:0123
henrike@webrtc.orgf0488722014-05-13 18:00:2624// Android has a 1024 limit on log inputs. We use 60 chars as an
25// approx for the header/tag portion.
26// See android/system/core/liblog/logd_write.c
27static const int kMaxLogLineSize = 1024 - 60;
28#endif // WEBRTC_MAC && !defined(WEBRTC_IOS) || WEBRTC_ANDROID
29
Yves Gerey988cc082018-10-23 10:03:0130#include <stdio.h>
31#include <string.h>
Yves Gerey665174f2018-06-19 13:03:0532#include <time.h>
Jonas Olssona4d87372019-07-05 17:08:3333
andresp@webrtc.orgff689be2015-02-12 11:54:2634#include <algorithm>
Karl Wibergcefc4652018-05-23 21:20:3835#include <cstdarg>
henrike@webrtc.orgf0488722014-05-13 18:00:2636#include <vector>
37
Yves Gerey988cc082018-10-23 10:03:0138#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 17:11:0039#include "rtc_base/critical_section.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3140#include "rtc_base/logging.h"
Tommie51a0a82018-02-27 14:30:2941#include "rtc_base/platform_thread_types.h"
Steve Anton10542f22019-01-11 17:11:0042#include "rtc_base/string_encode.h"
43#include "rtc_base/string_utils.h"
Tommifef05002018-02-27 12:51:0844#include "rtc_base/strings/string_builder.h"
Yves Gerey988cc082018-10-23 10:03:0145#include "rtc_base/thread_annotations.h"
Steve Anton10542f22019-01-11 17:11:0046#include "rtc_base/time_utils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2647
48namespace rtc {
andrew88703d72015-09-07 07:34:5649namespace {
Jonas Olsson2b6f1352018-02-15 10:57:0350// By default, release builds don't log, debug builds at info level
51#if !defined(NDEBUG)
52static LoggingSeverity g_min_sev = LS_INFO;
53static LoggingSeverity g_dbg_sev = LS_INFO;
54#else
55static LoggingSeverity g_min_sev = LS_NONE;
56static LoggingSeverity g_dbg_sev = LS_NONE;
57#endif
andrew88703d72015-09-07 07:34:5658
59// Return the filename portion of the string (that following the last slash).
60const char* FilenameFromPath(const char* file) {
61 const char* end1 = ::strrchr(file, '/');
62 const char* end2 = ::strrchr(file, '\\');
63 if (!end1 && !end2)
64 return file;
65 else
66 return (end1 > end2) ? end1 + 1 : end2 + 1;
67}
68
Jonas Olsson2b6f1352018-02-15 10:57:0369// Global lock for log subsystem, only needed to serialize access to streams_.
70CriticalSection g_log_crit;
andrew88703d72015-09-07 07:34:5671} // namespace
henrike@webrtc.orgf0488722014-05-13 18:00:2672
Paulina Hensmanf1e3cb42018-06-20 12:07:0573// Inefficient default implementation, override is recommended.
74void LogSink::OnLogMessage(const std::string& msg,
75 LoggingSeverity severity,
76 const char* tag) {
Jiawei Ou3ea18782018-11-01 06:14:2477 OnLogMessage(tag + (": " + msg), severity);
78}
79
80void LogSink::OnLogMessage(const std::string& msg,
81 LoggingSeverity /* severity */) {
82 OnLogMessage(msg);
Paulina Hensmanf1e3cb42018-06-20 12:07:0583}
84
henrike@webrtc.orgf0488722014-05-13 18:00:2685/////////////////////////////////////////////////////////////////////////////
86// LogMessage
87/////////////////////////////////////////////////////////////////////////////
88
andrew88703d72015-09-07 07:34:5689bool LogMessage::log_to_stderr_ = true;
henrike@webrtc.orgf0488722014-05-13 18:00:2690
henrike@webrtc.orgf0488722014-05-13 18:00:2691// The list of logging streams currently configured.
92// Note: we explicitly do not clean this up, because of the uncertain ordering
93// of destructors at program exit. Let the person who sets the stream trigger
deadbeef37f5ecf2017-02-27 22:06:4194// cleanup by setting to null, or let it leak (safe at program exit).
danilchap3c6abd22017-09-06 12:46:2995LogMessage::StreamList LogMessage::streams_ RTC_GUARDED_BY(g_log_crit);
henrike@webrtc.orgf0488722014-05-13 18:00:2696
97// Boolean options default to false (0)
98bool LogMessage::thread_, LogMessage::timestamp_;
99
Karl Wibergab4f1c12018-05-04 08:42:28100LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev)
101 : LogMessage(file, line, sev, ERRCTX_NONE, 0) {}
102
Peter Boström225789d2015-10-23 13:20:56103LogMessage::LogMessage(const char* file,
104 int line,
105 LoggingSeverity sev,
106 LogErrorContext err_ctx,
Tommie51a0a82018-02-27 14:30:29107 int err)
Jonas Olssond8c50782018-09-07 09:21:28108 : severity_(sev) {
henrike@webrtc.orgf0488722014-05-13 18:00:26109 if (timestamp_) {
Taylor Brandstetter4f0dfbd2016-06-16 00:15:23110 // Use SystemTimeMillis so that even if tests use fake clocks, the timestamp
111 // in log messages represents the real system time.
112 int64_t time = TimeDiff(SystemTimeMillis(), LogStartTime());
henrike@webrtc.orgf0488722014-05-13 18:00:26113 // Also ensure WallClockStartTime is initialized, so that it matches
114 // LogStartTime.
115 WallClockStartTime();
Jonas Olssond8c50782018-09-07 09:21:28116 print_stream_ << "[" << rtc::LeftPad('0', 3, rtc::ToString(time / 1000))
117 << ":" << rtc::LeftPad('0', 3, rtc::ToString(time % 1000))
henrike@webrtc.orgf0488722014-05-13 18:00:26118 << "] ";
119 }
120
121 if (thread_) {
henrikaba35d052015-07-14 15:04:08122 PlatformThreadId id = CurrentThreadId();
Jonas Olssond8c50782018-09-07 09:21:28123 print_stream_ << "[" << id << "] ";
henrike@webrtc.orgf0488722014-05-13 18:00:26124 }
125
Paulina Hensmanf1e3cb42018-06-20 12:07:05126 if (file != nullptr) {
127#if defined(WEBRTC_ANDROID)
128 tag_ = FilenameFromPath(file);
129 print_stream_ << "(line " << line << "): ";
130#else
Yves Gerey665174f2018-06-19 13:03:05131 print_stream_ << "(" << FilenameFromPath(file) << ":" << line << "): ";
Paulina Hensmanf1e3cb42018-06-20 12:07:05132#endif
133 }
andrew88703d72015-09-07 07:34:56134
henrike@webrtc.orgf0488722014-05-13 18:00:26135 if (err_ctx != ERRCTX_NONE) {
Karl Wiberg881f1682018-03-08 14:03:23136 char tmp_buf[1024];
137 SimpleStringBuilder tmp(tmp_buf);
Tommifef05002018-02-27 12:51:08138 tmp.AppendFormat("[0x%08X]", err);
henrike@webrtc.orgf0488722014-05-13 18:00:26139 switch (err_ctx) {
140 case ERRCTX_ERRNO:
141 tmp << " " << strerror(err);
142 break;
kwiberg77eab702016-09-29 00:42:01143#ifdef WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26144 case ERRCTX_HRESULT: {
145 char msgbuf[256];
Yves Gerey665174f2018-06-19 13:03:05146 DWORD flags =
147 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
henrike@webrtc.orgf0488722014-05-13 18:00:26148 if (DWORD len = FormatMessageA(
Tommie51a0a82018-02-27 14:30:29149 flags, nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
deadbeef37f5ecf2017-02-27 22:06:41150 msgbuf, sizeof(msgbuf) / sizeof(msgbuf[0]), nullptr)) {
henrike@webrtc.orgf0488722014-05-13 18:00:26151 while ((len > 0) &&
Yves Gerey665174f2018-06-19 13:03:05152 isspace(static_cast<unsigned char>(msgbuf[len - 1]))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26153 msgbuf[--len] = 0;
154 }
155 tmp << " " << msgbuf;
156 }
157 break;
158 }
Tommi0eefb4d2015-05-23 07:54:07159#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26160 default:
161 break;
162 }
163 extra_ = tmp.str();
164 }
165}
166
Tommie51a0a82018-02-27 14:30:29167#if defined(WEBRTC_ANDROID)
jiayl66f0da22015-09-14 22:06:39168LogMessage::LogMessage(const char* file,
169 int line,
170 LoggingSeverity sev,
Tommie51a0a82018-02-27 14:30:29171 const char* tag)
Yves Gerey665174f2018-06-19 13:03:05172 : LogMessage(file, line, sev, ERRCTX_NONE, 0 /* err */) {
Jonas Olssond8c50782018-09-07 09:21:28173 tag_ = tag;
174 print_stream_ << tag << ": ";
jiayl66f0da22015-09-14 22:06:39175}
Tommie51a0a82018-02-27 14:30:29176#endif
177
178// DEPRECATED. Currently only used by downstream projects that use
179// implementation details of logging.h. Work is ongoing to remove those
180// dependencies.
Yves Gerey665174f2018-06-19 13:03:05181LogMessage::LogMessage(const char* file,
182 int line,
183 LoggingSeverity sev,
Tommie51a0a82018-02-27 14:30:29184 const std::string& tag)
185 : LogMessage(file, line, sev) {
Jonas Olssond8c50782018-09-07 09:21:28186 print_stream_ << tag << ": ";
Tommie51a0a82018-02-27 14:30:29187}
jiayl66f0da22015-09-14 22:06:39188
henrike@webrtc.orgf0488722014-05-13 18:00:26189LogMessage::~LogMessage() {
Tommifef05002018-02-27 12:51:08190 FinishPrintStream();
191
Jonas Olssond8c50782018-09-07 09:21:28192 const std::string str = print_stream_.Release();
Tommifef05002018-02-27 12:51:08193
Jonas Olsson2b6f1352018-02-15 10:57:03194 if (severity_ >= g_dbg_sev) {
Tommie51a0a82018-02-27 14:30:29195#if defined(WEBRTC_ANDROID)
jiayl66f0da22015-09-14 22:06:39196 OutputToDebug(str, severity_, tag_);
Tommie51a0a82018-02-27 14:30:29197#else
198 OutputToDebug(str, severity_);
199#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26200 }
201
Peter Boström225789d2015-10-23 13:20:56202 CritScope cs(&g_log_crit);
203 for (auto& kv : streams_) {
204 if (severity_ >= kv.second) {
Paulina Hensmanf1e3cb42018-06-20 12:07:05205#if defined(WEBRTC_ANDROID)
206 kv.first->OnLogMessage(str, severity_, tag_);
207#else
Jiawei Ou3ea18782018-11-01 06:14:24208 kv.first->OnLogMessage(str, severity_);
Paulina Hensmanf1e3cb42018-06-20 12:07:05209#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26210 }
211 }
henrike@webrtc.orgf0488722014-05-13 18:00:26212}
213
Karl Wibergcefc4652018-05-23 21:20:38214void LogMessage::AddTag(const char* tag) {
215#ifdef WEBRTC_ANDROID
Jonas Olssond8c50782018-09-07 09:21:28216 tag_ = tag;
Karl Wibergcefc4652018-05-23 21:20:38217#endif
218}
219
Jonas Olssond8c50782018-09-07 09:21:28220rtc::StringBuilder& LogMessage::stream() {
221 return print_stream_;
Jonas Olsson2b6f1352018-02-15 10:57:03222}
223
224int LogMessage::GetMinLogSeverity() {
225 return g_min_sev;
226}
227
228LoggingSeverity LogMessage::GetLogToDebug() {
229 return g_dbg_sev;
230}
Honghai Zhang82d78622016-05-06 18:29:15231int64_t LogMessage::LogStartTime() {
Taylor Brandstetter4f0dfbd2016-06-16 00:15:23232 static const int64_t g_start = SystemTimeMillis();
henrike@webrtc.orgf0488722014-05-13 18:00:26233 return g_start;
234}
235
Peter Boström0c4e06b2015-10-07 10:23:21236uint32_t LogMessage::WallClockStartTime() {
deadbeef37f5ecf2017-02-27 22:06:41237 static const uint32_t g_start_wallclock = time(nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26238 return g_start_wallclock;
239}
240
henrike@webrtc.orgf0488722014-05-13 18:00:26241void LogMessage::LogThreads(bool on) {
242 thread_ = on;
243}
244
245void LogMessage::LogTimestamps(bool on) {
246 timestamp_ = on;
247}
248
Tommi0eefb4d2015-05-23 07:54:07249void LogMessage::LogToDebug(LoggingSeverity min_sev) {
Jonas Olsson2b6f1352018-02-15 10:57:03250 g_dbg_sev = min_sev;
Peter Boström225789d2015-10-23 13:20:56251 CritScope cs(&g_log_crit);
Tommi00aac5a2015-05-25 09:25:59252 UpdateMinLogSeverity();
henrike@webrtc.orgf0488722014-05-13 18:00:26253}
254
andrew88703d72015-09-07 07:34:56255void LogMessage::SetLogToStderr(bool log_to_stderr) {
256 log_to_stderr_ = log_to_stderr;
257}
258
Tommi0eefb4d2015-05-23 07:54:07259int LogMessage::GetLogToStream(LogSink* stream) {
Peter Boström225789d2015-10-23 13:20:56260 CritScope cs(&g_log_crit);
Tommi0eefb4d2015-05-23 07:54:07261 LoggingSeverity sev = LS_NONE;
Peter Boström225789d2015-10-23 13:20:56262 for (auto& kv : streams_) {
263 if (!stream || stream == kv.first) {
264 sev = std::min(sev, kv.second);
henrike@webrtc.orgf0488722014-05-13 18:00:26265 }
266 }
267 return sev;
268}
269
Tommi0eefb4d2015-05-23 07:54:07270void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) {
Peter Boström225789d2015-10-23 13:20:56271 CritScope cs(&g_log_crit);
henrike@webrtc.orgf0488722014-05-13 18:00:26272 streams_.push_back(std::make_pair(stream, min_sev));
273 UpdateMinLogSeverity();
274}
275
Tommi0eefb4d2015-05-23 07:54:07276void LogMessage::RemoveLogToStream(LogSink* stream) {
Peter Boström225789d2015-10-23 13:20:56277 CritScope cs(&g_log_crit);
henrike@webrtc.orgf0488722014-05-13 18:00:26278 for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
279 if (stream == it->first) {
280 streams_.erase(it);
281 break;
282 }
283 }
284 UpdateMinLogSeverity();
285}
286
Tommi0eefb4d2015-05-23 07:54:07287void LogMessage::ConfigureLogging(const char* params) {
288 LoggingSeverity current_level = LS_VERBOSE;
289 LoggingSeverity debug_level = GetLogToDebug();
henrike@webrtc.orgf0488722014-05-13 18:00:26290
291 std::vector<std::string> tokens;
292 tokenize(params, ' ', &tokens);
293
Tommi0eefb4d2015-05-23 07:54:07294 for (const std::string& token : tokens) {
295 if (token.empty())
henrike@webrtc.orgf0488722014-05-13 18:00:26296 continue;
297
298 // Logging features
Tommi0eefb4d2015-05-23 07:54:07299 if (token == "tstamp") {
henrike@webrtc.orgf0488722014-05-13 18:00:26300 LogTimestamps();
Tommi0eefb4d2015-05-23 07:54:07301 } else if (token == "thread") {
henrike@webrtc.orgf0488722014-05-13 18:00:26302 LogThreads();
303
Yves Gerey665174f2018-06-19 13:03:05304 // Logging levels
Tommi0eefb4d2015-05-23 07:54:07305 } else if (token == "verbose") {
henrike@webrtc.orgf0488722014-05-13 18:00:26306 current_level = LS_VERBOSE;
Tommi0eefb4d2015-05-23 07:54:07307 } else if (token == "info") {
henrike@webrtc.orgf0488722014-05-13 18:00:26308 current_level = LS_INFO;
Tommi0eefb4d2015-05-23 07:54:07309 } else if (token == "warning") {
henrike@webrtc.orgf0488722014-05-13 18:00:26310 current_level = LS_WARNING;
Tommi0eefb4d2015-05-23 07:54:07311 } else if (token == "error") {
henrike@webrtc.orgf0488722014-05-13 18:00:26312 current_level = LS_ERROR;
Tommi0eefb4d2015-05-23 07:54:07313 } else if (token == "none") {
314 current_level = LS_NONE;
henrike@webrtc.orgf0488722014-05-13 18:00:26315
Yves Gerey665174f2018-06-19 13:03:05316 // Logging targets
Tommi0eefb4d2015-05-23 07:54:07317 } else if (token == "debug") {
henrike@webrtc.orgf0488722014-05-13 18:00:26318 debug_level = current_level;
319 }
320 }
321
Robin Raymondce1b1402018-11-23 01:10:11322#if defined(WEBRTC_WIN) && !defined(WINUWP)
Tommi0eefb4d2015-05-23 07:54:07323 if ((LS_NONE != debug_level) && !::IsDebuggerPresent()) {
henrike@webrtc.orgf0488722014-05-13 18:00:26324 // First, attempt to attach to our parent's console... so if you invoke
325 // from the command line, we'll see the output there. Otherwise, create
326 // our own console window.
327 // Note: These methods fail if a console already exists, which is fine.
Tommie51a0a82018-02-27 14:30:29328 if (!AttachConsole(ATTACH_PARENT_PROCESS))
henrike@webrtc.orgf0488722014-05-13 18:00:26329 ::AllocConsole();
henrike@webrtc.orgf0488722014-05-13 18:00:26330 }
Robin Raymondce1b1402018-11-23 01:10:11331#endif // defined(WEBRTC_WIN) && !defined(WINUWP)
henrike@webrtc.orgf0488722014-05-13 18:00:26332
333 LogToDebug(debug_level);
henrike@webrtc.orgf0488722014-05-13 18:00:26334}
335
danilchap3c6abd22017-09-06 12:46:29336void LogMessage::UpdateMinLogSeverity()
337 RTC_EXCLUSIVE_LOCKS_REQUIRED(g_log_crit) {
Jonas Olsson2b6f1352018-02-15 10:57:03338 LoggingSeverity min_sev = g_dbg_sev;
Karl Wibergd294c852018-06-12 09:31:06339 for (const auto& kv : streams_) {
340 const LoggingSeverity sev = kv.second;
341 min_sev = std::min(min_sev, sev);
henrike@webrtc.orgf0488722014-05-13 18:00:26342 }
Jonas Olsson2b6f1352018-02-15 10:57:03343 g_min_sev = min_sev;
henrike@webrtc.orgf0488722014-05-13 18:00:26344}
345
Tommie51a0a82018-02-27 14:30:29346#if defined(WEBRTC_ANDROID)
henrike@webrtc.orgf0488722014-05-13 18:00:26347void LogMessage::OutputToDebug(const std::string& str,
jiayl66f0da22015-09-14 22:06:39348 LoggingSeverity severity,
Tommie51a0a82018-02-27 14:30:29349 const char* tag) {
350#else
351void LogMessage::OutputToDebug(const std::string& str,
352 LoggingSeverity severity) {
353#endif
andrew88703d72015-09-07 07:34:56354 bool log_to_stderr = log_to_stderr_;
tfarinaa41ab932015-10-30 23:08:48355#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) && defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26356 // On the Mac, all stderr output goes to the Console log and causes clutter.
357 // So in opt builds, don't log to stderr unless the user specifically sets
358 // a preference to do so.
Yves Gerey665174f2018-06-19 13:03:05359 CFStringRef key = CFStringCreateWithCString(
360 kCFAllocatorDefault, "logToStdErr", kCFStringEncodingUTF8);
henrike@webrtc.orgf0488722014-05-13 18:00:26361 CFStringRef domain = CFBundleGetIdentifier(CFBundleGetMainBundle());
deadbeef37f5ecf2017-02-27 22:06:41362 if (key != nullptr && domain != nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26363 Boolean exists_and_is_valid;
364 Boolean should_log =
365 CFPreferencesGetAppBooleanValue(key, domain, &exists_and_is_valid);
366 // If the key doesn't exist or is invalid or is false, we will not log to
367 // stderr.
368 log_to_stderr = exists_and_is_valid && should_log;
369 }
deadbeef37f5ecf2017-02-27 22:06:41370 if (key != nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26371 CFRelease(key);
372 }
Tommie51a0a82018-02-27 14:30:29373#endif // defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) && defined(NDEBUG)
374
henrike@webrtc.orgf0488722014-05-13 18:00:26375#if defined(WEBRTC_WIN)
376 // Always log to the debugger.
377 // Perhaps stderr should be controlled by a preference, as on Mac?
378 OutputDebugStringA(str.c_str());
379 if (log_to_stderr) {
380 // This handles dynamically allocated consoles, too.
381 if (HANDLE error_handle = ::GetStdHandle(STD_ERROR_HANDLE)) {
382 log_to_stderr = false;
383 DWORD written = 0;
384 ::WriteFile(error_handle, str.data(), static_cast<DWORD>(str.size()),
385 &written, 0);
386 }
387 }
Tommi0eefb4d2015-05-23 07:54:07388#endif // WEBRTC_WIN
Tommie51a0a82018-02-27 14:30:29389
henrike@webrtc.orgf0488722014-05-13 18:00:26390#if defined(WEBRTC_ANDROID)
391 // Android's logging facility uses severity to log messages but we
392 // need to map libjingle's severity levels to Android ones first.
393 // Also write to stderr which maybe available to executable started
394 // from the shell.
395 int prio;
396 switch (severity) {
henrike@webrtc.orgf0488722014-05-13 18:00:26397 case LS_VERBOSE:
398 prio = ANDROID_LOG_VERBOSE;
399 break;
400 case LS_INFO:
401 prio = ANDROID_LOG_INFO;
402 break;
403 case LS_WARNING:
404 prio = ANDROID_LOG_WARN;
405 break;
406 case LS_ERROR:
407 prio = ANDROID_LOG_ERROR;
408 break;
409 default:
410 prio = ANDROID_LOG_UNKNOWN;
411 }
412
413 int size = str.size();
414 int line = 0;
415 int idx = 0;
416 const int max_lines = size / kMaxLogLineSize + 1;
417 if (max_lines == 1) {
Tommie51a0a82018-02-27 14:30:29418 __android_log_print(prio, tag, "%.*s", size, str.c_str());
henrike@webrtc.orgf0488722014-05-13 18:00:26419 } else {
420 while (size > 0) {
421 const int len = std::min(size, kMaxLogLineSize);
422 // Use the size of the string in the format (str may have \0 in the
423 // middle).
Tommie51a0a82018-02-27 14:30:29424 __android_log_print(prio, tag, "[%d/%d] %.*s", line + 1, max_lines, len,
425 str.c_str() + idx);
henrike@webrtc.orgf0488722014-05-13 18:00:26426 idx += len;
427 size -= len;
428 ++line;
429 }
430 }
431#endif // WEBRTC_ANDROID
432 if (log_to_stderr) {
433 fprintf(stderr, "%s", str.c_str());
434 fflush(stderr);
435 }
436}
437
Tommifef05002018-02-27 12:51:08438// static
439bool LogMessage::IsNoop(LoggingSeverity severity) {
Jonas Olssond8c50782018-09-07 09:21:28440 if (severity >= g_dbg_sev || severity >= g_min_sev)
Tommifef05002018-02-27 12:51:08441 return false;
442
443 // TODO(tommi): We're grabbing this lock for every LogMessage instance that
444 // is going to be logged. This introduces unnecessary synchronization for
445 // a feature that's mostly used for testing.
446 CritScope cs(&g_log_crit);
Jonas Olssond8c50782018-09-07 09:21:28447 if (streams_.size() > 0)
448 return false;
449
450 return true;
Tommifef05002018-02-27 12:51:08451}
452
453void LogMessage::FinishPrintStream() {
Tommifef05002018-02-27 12:51:08454 if (!extra_.empty())
455 print_stream_ << " : " << extra_;
Jonas Olssond8c50782018-09-07 09:21:28456 print_stream_ << "\n";
Tommifef05002018-02-27 12:51:08457}
458
Karl Wibergcefc4652018-05-23 21:20:38459namespace webrtc_logging_impl {
henrike@webrtc.orgf0488722014-05-13 18:00:26460
Karl Wibergcefc4652018-05-23 21:20:38461void Log(const LogArgType* fmt, ...) {
462 va_list args;
463 va_start(args, fmt);
464
465 LogMetadataErr meta;
466 const char* tag = nullptr;
467 switch (*fmt) {
468 case LogArgType::kLogMetadata: {
469 meta = {va_arg(args, LogMetadata), ERRCTX_NONE, 0};
470 break;
471 }
472 case LogArgType::kLogMetadataErr: {
473 meta = va_arg(args, LogMetadataErr);
474 break;
475 }
476#ifdef WEBRTC_ANDROID
477 case LogArgType::kLogMetadataTag: {
478 const LogMetadataTag tag_meta = va_arg(args, LogMetadataTag);
479 meta = {{nullptr, 0, tag_meta.severity}, ERRCTX_NONE, 0};
480 tag = tag_meta.tag;
481 break;
482 }
483#endif
484 default: {
485 RTC_NOTREACHED();
486 va_end(args);
487 return;
488 }
489 }
Jonas Olssond8c50782018-09-07 09:21:28490
491 if (LogMessage::IsNoop(meta.meta.Severity())) {
492 va_end(args);
493 return;
494 }
495
Karl Wibergcefc4652018-05-23 21:20:38496 LogMessage log_message(meta.meta.File(), meta.meta.Line(),
497 meta.meta.Severity(), meta.err_ctx, meta.err);
498 if (tag) {
499 log_message.AddTag(tag);
500 }
501
502 for (++fmt; *fmt != LogArgType::kEnd; ++fmt) {
503 switch (*fmt) {
504 case LogArgType::kInt:
505 log_message.stream() << va_arg(args, int);
506 break;
507 case LogArgType::kLong:
508 log_message.stream() << va_arg(args, long);
509 break;
510 case LogArgType::kLongLong:
511 log_message.stream() << va_arg(args, long long);
512 break;
513 case LogArgType::kUInt:
514 log_message.stream() << va_arg(args, unsigned);
515 break;
516 case LogArgType::kULong:
517 log_message.stream() << va_arg(args, unsigned long);
518 break;
519 case LogArgType::kULongLong:
520 log_message.stream() << va_arg(args, unsigned long long);
521 break;
522 case LogArgType::kDouble:
523 log_message.stream() << va_arg(args, double);
524 break;
525 case LogArgType::kLongDouble:
526 log_message.stream() << va_arg(args, long double);
527 break;
Niels Möller65835be2019-02-04 18:23:58528 case LogArgType::kCharP: {
529 const char* s = va_arg(args, const char*);
530 log_message.stream() << (s ? s : "(null)");
Karl Wibergcefc4652018-05-23 21:20:38531 break;
Niels Möller65835be2019-02-04 18:23:58532 }
Karl Wibergcefc4652018-05-23 21:20:38533 case LogArgType::kStdString:
534 log_message.stream() << *va_arg(args, const std::string*);
535 break;
Jonas Olssonf2ce37c2018-09-12 13:32:47536 case LogArgType::kStringView:
537 log_message.stream() << *va_arg(args, const absl::string_view*);
538 break;
Karl Wibergcefc4652018-05-23 21:20:38539 case LogArgType::kVoidP:
Jonas Olssond8c50782018-09-07 09:21:28540 log_message.stream() << rtc::ToHex(
541 reinterpret_cast<uintptr_t>(va_arg(args, const void*)));
Karl Wibergcefc4652018-05-23 21:20:38542 break;
543 default:
544 RTC_NOTREACHED();
545 va_end(args);
546 return;
547 }
548 }
549
550 va_end(args);
551}
552
553} // namespace webrtc_logging_impl
henrike@webrtc.orgf0488722014-05-13 18:00:26554} // namespace rtc