1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This file overrides the logging macros in libjingle (talk/base/logging.h).
6// Instead of using libjingle's logging implementation, the libjingle macros are
7// mapped to the corresponding base/logging.h macro (chromium's VLOG).
8// If this file is included outside of libjingle (e.g. in wrapper code) it
9// should be included after base/logging.h (if any) or compiler error or
10// unexpected behavior may occur (macros that have the same name in libjingle as
11// in chromium will use the libjingle definition if this file is included
12// first).
13
14// Setting the LoggingSeverity (and lower) that should be written to file should
15// be done via command line by specifying the flags:
16// --vmodule or --v please see base/logging.h for details on how to use them.
17// Specifying what file to write to is done using InitLogging also in
18// base/logging.h.
19
20// The macros and classes declared in here are not described as they are
21// NOT TO BE USED outside of libjingle.
22
23#ifndef THIRD_PARTY_LIBJINGLE_OVERRIDES_TALK_BASE_LOGGING_H_
24#define THIRD_PARTY_LIBJINGLE_OVERRIDES_TALK_BASE_LOGGING_H_
25
26#include <sstream>
27#include <string>
28
29#include "base/logging.h"
30#include "third_party/libjingle/source/talk/base/scoped_ref_ptr.h"
31
32namespace talk_base {
33
34///////////////////////////////////////////////////////////////////////////////
35// ConstantLabel can be used to easily generate string names from constant
36// values.  This can be useful for logging descriptive names of error messages.
37// Usage:
38//   const ConstantLabel LIBRARY_ERRORS[] = {
39//     KLABEL(SOME_ERROR),
40//     KLABEL(SOME_OTHER_ERROR),
41//     ...
42//     LASTLABEL
43//   }
44//
45//   int err = LibraryFunc();
46//   LOG(LS_ERROR) << "LibraryFunc returned: "
47//                 << ErrorName(err, LIBRARY_ERRORS);
48
49struct ConstantLabel {
50  int value;
51  const char* label;
52};
53#define KLABEL(x) { x, #x }
54#define LASTLABEL { 0, 0 }
55
56const char* FindLabel(int value, const ConstantLabel entries[]);
57std::string ErrorName(int err, const ConstantLabel* err_table);
58
59//////////////////////////////////////////////////////////////////////
60// Note that the non-standard LoggingSeverity aliases exist because they are
61// still in broad use.  The meanings of the levels are:
62//  LS_SENSITIVE: Information which should only be logged with the consent
63//   of the user, due to privacy concerns.
64//  LS_VERBOSE: This level is for data which we do not want to appear in the
65//   normal debug log, but should appear in diagnostic logs.
66//  LS_INFO: Chatty level used in debugging for all sorts of things, the default
67//   in debug builds.
68//  LS_WARNING: Something that may warrant investigation.
69//  LS_ERROR: Something that should not have occurred.
70// Note that LoggingSeverity is mapped over to chromiums verbosity levels where
71// anything lower than or equal to the current verbosity level is written to
72// file which is the opposite of logging severity in libjingle where higher
73// severity numbers than or equal to the current severity level are written to
74// file. Also, note that the values are explicitly defined here for convenience
75// since the command line flag must be set using numerical values.
76enum LoggingSeverity { LS_ERROR = 1,
77                       LS_WARNING = 2,
78                       LS_INFO = 3,
79                       LS_VERBOSE = 4,
80                       LS_SENSITIVE = 5,
81                       INFO = LS_INFO,
82                       WARNING = LS_WARNING,
83                       LERROR = LS_ERROR };
84
85// LogErrorContext assists in interpreting the meaning of an error value.
86enum LogErrorContext {
87  ERRCTX_NONE,
88  ERRCTX_ERRNO,     // System-local errno
89  ERRCTX_HRESULT,   // Windows HRESULT
90  ERRCTX_OSSTATUS,  // MacOS OSStatus
91
92  // Abbreviations for LOG_E macro
93  ERRCTX_EN = ERRCTX_ERRNO,     // LOG_E(sev, EN, x)
94  ERRCTX_HR = ERRCTX_HRESULT,   // LOG_E(sev, HR, x)
95  ERRCTX_OS = ERRCTX_OSSTATUS,  // LOG_E(sev, OS, x)
96};
97
98// Class that writes a log message to the logging delegate ("WebRTC logging
99// stream" in Chrome) and to Chrome's logging stream.
100class DiagnosticLogMessage {
101 public:
102  DiagnosticLogMessage(const char* file, int line, LoggingSeverity severity,
103                       bool log_to_chrome, LogErrorContext err_ctx, int err);
104  DiagnosticLogMessage(const char* file, int line, LoggingSeverity severity,
105                       bool log_to_chrome, LogErrorContext err_ctx, int err,
106                       const char* module);
107  ~DiagnosticLogMessage();
108
109  void CreateTimestamp();
110
111  std::ostream& stream() { return print_stream_; }
112
113 private:
114  const char* file_name_;
115  const int line_;
116  const LoggingSeverity severity_;
117  const bool log_to_chrome_;
118
119  std::string extra_;
120
121  std::ostringstream print_stream_;
122  std::ostringstream print_stream_with_timestamp_;
123};
124
125// This class is used to explicitly ignore values in the conditional
126// logging macros.  This avoids compiler warnings like "value computed
127// is not used" and "statement has no effect".
128class LogMessageVoidify {
129 public:
130  LogMessageVoidify() { }
131  // This has to be an operator with a precedence lower than << but
132  // higher than ?:
133  void operator&(std::ostream&) { }
134};
135
136//////////////////////////////////////////////////////////////////////
137// Logging Helpers
138//////////////////////////////////////////////////////////////////////
139
140class LogMultilineState {
141 public:
142  size_t unprintable_count_[2];
143  LogMultilineState() {
144    unprintable_count_[0] = unprintable_count_[1] = 0;
145  }
146};
147
148// When possible, pass optional state variable to track various data across
149// multiple calls to LogMultiline.  Otherwise, pass NULL.
150void LogMultiline(LoggingSeverity level, const char* label, bool input,
151                  const void* data, size_t len, bool hex_mode,
152                  LogMultilineState* state);
153
154void InitDiagnosticLoggingDelegateFunction(
155    void (*delegate)(const std::string&));
156
157}  // namespace talk_base
158
159//////////////////////////////////////////////////////////////////////
160// Libjingle macros which are mapped over to their VLOG equivalent in
161// base/logging.h
162//////////////////////////////////////////////////////////////////////
163
164#if defined(LOGGING_INSIDE_LIBJINGLE)
165
166#define DIAGNOSTIC_LOG(sev, ctx, err, ...) \
167  talk_base::DiagnosticLogMessage( \
168      __FILE__, __LINE__, sev, VLOG_IS_ON(sev), \
169      talk_base::ERRCTX_ ## ctx, err, ##__VA_ARGS__).stream()
170
171#define LOG_CHECK_LEVEL(sev) VLOG_IS_ON(talk_base::sev)
172#define LOG_CHECK_LEVEL_V(sev) VLOG_IS_ON(sev)
173
174#define LOG_V(sev) DIAGNOSTIC_LOG(sev, NONE, 0)
175#undef LOG
176#define LOG(sev) DIAGNOSTIC_LOG(talk_base::sev, NONE, 0)
177
178// The _F version prefixes the message with the current function name.
179#if defined(__GNUC__) && defined(_DEBUG)
180#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
181#else
182#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
183#endif
184
185#define LOG_E(sev, ctx, err, ...) \
186  DIAGNOSTIC_LOG(talk_base::sev, ctx, err, ##__VA_ARGS__)
187
188#undef LOG_ERRNO_EX
189#define LOG_ERRNO_EX(sev, err) LOG_E(sev, ERRNO, err)
190#undef LOG_ERRNO
191#define LOG_ERRNO(sev) LOG_ERRNO_EX(sev, errno)
192
193#if defined(OS_WIN)
194#define LOG_GLE_EX(sev, err) LOG_E(sev, HRESULT, err)
195#define LOG_GLE(sev) LOG_GLE_EX(sev, GetLastError())
196#define LOG_GLEM(sev, mod) LOG_E(sev, HRESULT, GetLastError(), mod)
197#define LOG_ERR_EX(sev, err) LOG_GLE_EX(sev, err)
198#define LOG_ERR(sev) LOG_GLE(sev)
199#define LAST_SYSTEM_ERROR (::GetLastError())
200#else
201#define LOG_ERR_EX(sev, err) LOG_ERRNO_EX(sev, err)
202#define LOG_ERR(sev) LOG_ERRNO(sev)
203#define LAST_SYSTEM_ERROR (errno)
204#endif  // OS_WIN
205
206#undef PLOG
207#define PLOG(sev, err) LOG_ERR_EX(sev, err)
208
209#endif  // LOGGING_INSIDE_LIBJINGLE
210
211#endif  // THIRD_PARTY_LIBJINGLE_OVERRIDES_TALK_BASE_LOGGING_H_
212