1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   LOG(...) an ostream target that can be used to send formatted
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// output to a variety of logging targets, such as debugger console, stderr,
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// file, or any StreamInterface.
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   The severity level passed as the first argument to the the LOGging
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// functions is used as a filter, to limit the verbosity of the logging.
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   Static members of LogMessage documented below are used to control the
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// verbosity and target of the output.
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   There are several variations on the LOG macro which facilitate logging
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// of common error conditions, detailed below.
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LOG(sev) logs the given stream at severity "sev", which must be a
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     compile-time constant of the LoggingSeverity type, without the namespace
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     prefix.
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     type (basically, it just doesn't prepend the namespace).
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LOG_F(sev) Like LOG(), but includes the name of the current function.
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LOG_GLE(M)(sev [, mod]) attempt to add a string description of the
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     HRESULT returned by GetLastError.  The "M" variant allows searching of a
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     DLL's string table for the error description.
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LOG_ERRNO(sev) attempts to add a string description of an errno-derived
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     error. errno and associated facilities exist on both Windows and POSIX,
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     but on Windows they only apply to the C/C++ runtime.
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LOG_ERR(sev) is an alias for the platform's normal error system, i.e. _GLE on
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     Windows and _ERRNO on POSIX.
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// (The above three also all have _EX versions that let you specify the error
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// code, rather than using the last one.)
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LOG_E(sev, ctx, err, ...) logs a detailed error interpreted using the
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     specified context.
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LOG_CHECK_LEVEL(sev) (and LOG_CHECK_LEVEL_V(sev)) can be used as a test
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     before performing expensive or sensitive operations whose sole purpose is
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     to output logging data at the desired level.
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Lastly, PLOG(sev, err) is an alias for LOG_ERR_EX.
60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifndef TALK_BASE_LOGGING_H_
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define TALK_BASE_LOGGING_H_
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef HAVE_CONFIG_H
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "config.h"  // NOLINT
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <list>
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <sstream>
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <string>
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <utility>
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/basictypes.h"
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/criticalsection.h"
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base {
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass StreamInterface;
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch///////////////////////////////////////////////////////////////////////////////
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// ConstantLabel can be used to easily generate string names from constant
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// values.  This can be useful for logging descriptive names of error messages.
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Usage:
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   const ConstantLabel LIBRARY_ERRORS[] = {
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     KLABEL(SOME_ERROR),
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     KLABEL(SOME_OTHER_ERROR),
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     ...
87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     LASTLABEL
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   }
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   int err = LibraryFunc();
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   LOG(LS_ERROR) << "LibraryFunc returned: "
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                 << ErrorName(err, LIBRARY_ERRORS);
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstruct ConstantLabel { int value; const char * label; };
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(SAFE_TO_DEFINE_TALK_BASE_LOGGING_MACROS)
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define KLABEL(x) { x, #x }
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define TLABEL(x, y) { x, y }
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LASTLABEL { 0, 0 }
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // defined(SAFE_TO_DEFINE_TALK_BASE_LOGGING_MACROS)
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char * FindLabel(int value, const ConstantLabel entries[]);
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string ErrorName(int err, const ConstantLabel* err_table);
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Note that the non-standard LoggingSeverity aliases exist because they are
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// still in broad use.  The meanings of the levels are:
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//  LS_SENSITIVE: Information which should only be logged with the consent
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   of the user, due to privacy concerns.
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//  LS_VERBOSE: This level is for data which we do not want to appear in the
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   normal debug log, but should appear in diagnostic logs.
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//  LS_INFO: Chatty level used in debugging for all sorts of things, the default
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   in debug builds.
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//  LS_WARNING: Something that may warrant investigation.
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//  LS_ERROR: Something that should not have occurred.
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochenum LoggingSeverity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR,
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                       INFO = LS_INFO,
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                       WARNING = LS_WARNING,
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                       LERROR = LS_ERROR };
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// LogErrorContext assists in interpreting the meaning of an error value.
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochenum LogErrorContext {
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ERRCTX_NONE,
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ERRCTX_ERRNO,     // System-local errno
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ERRCTX_HRESULT,   // Windows HRESULT
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ERRCTX_OSSTATUS,  // MacOS OSStatus
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Abbreviations for LOG_E macro
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ERRCTX_EN = ERRCTX_ERRNO,     // LOG_E(sev, EN, x)
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ERRCTX_HR = ERRCTX_HRESULT,   // LOG_E(sev, HR, x)
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ERRCTX_OS = ERRCTX_OSSTATUS,  // LOG_E(sev, OS, x)
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass LogMessage {
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static const int NO_LOGGING;
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LogMessage(const char* file, int line, LoggingSeverity sev,
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch             LogErrorContext err_ctx = ERRCTX_NONE, int err = 0,
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch             const char* module = NULL);
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ~LogMessage();
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static inline bool Loggable(LoggingSeverity sev) { return (sev >= min_sev_); }
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::ostream& stream() { return print_stream_; }
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // These are attributes which apply to all logging channels
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //  LogContext: Display the file and line number of the message
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void LogContext(int min_sev);
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //  LogThreads: Display the thread identifier of the current thread
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void LogThreads(bool on = true);
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //  LogTimestamps: Display the elapsed time of the program
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void LogTimestamps(bool on = true);
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Timestamps begin with program execution, but can be reset with this
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // function for measuring the duration of an activity, or to synchronize
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // timestamps between multiple instances.
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void ResetTimestamps();
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // These are the available logging channels
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //  Debug: Debug console on Windows, otherwise stderr
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void LogToDebug(int min_sev);
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static int GetLogToDebug() { return dbg_sev_; }
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //  Stream: Any non-blocking stream interface.  LogMessage takes ownership of
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //   the stream. Multiple streams may be specified by using AddLogToStream.
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //   LogToStream is retained for backwards compatibility; when invoked, it
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //   will discard any previously set streams and install the specified stream.
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //   GetLogToStream gets the severity for the specified stream, of if none
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //   is specified, the minimum stream severity.
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //   RemoveLogToStream removes the specified stream, without destroying it.
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void LogToStream(StreamInterface* stream, int min_sev);
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static int GetLogToStream(StreamInterface* stream = NULL);
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void AddLogToStream(StreamInterface* stream, int min_sev);
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void RemoveLogToStream(StreamInterface* stream);
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Testing against MinLogSeverity allows code to avoid potentially expensive
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // logging operations by pre-checking the logging level.
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static int GetMinLogSeverity() { return min_sev_; }
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void SetDiagnosticMode(bool f) { is_diagnostic_mode_ = f; }
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static bool IsDiagnosticMode() { return is_diagnostic_mode_; }
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Parses the provided parameter stream to configure the options above.
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Useful for configuring logging from the command line.  If file logging
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // is enabled, it is output to the specified filename.
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void ConfigureLogging(const char* params, const char* filename);
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Convert the string to a LS_ value; also accept numeric values.
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static int ParseLogSeverity(const std::string& value);
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private:
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  typedef std::list<std::pair<StreamInterface*, int> > StreamList;
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Updates min_sev_ appropriately when debug sinks change.
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void UpdateMinLogSeverity();
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // These assist in formatting some parts of the debug output.
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static const char* Describe(LoggingSeverity sev);
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static const char* DescribeFile(const char* file);
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // These write out the actual log messages.
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void OutputToDebug(const std::string& msg, LoggingSeverity severity_);
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static void OutputToStream(StreamInterface* stream, const std::string& msg);
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // The ostream that buffers the formatted message before output
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::ostringstream print_stream_;
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // The severity level of this message
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LoggingSeverity severity_;
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // String data generated in the constructor, that should be appended to
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // the message before output.
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string extra_;
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Global lock for the logging subsystem
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static CriticalSection crit_;
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // dbg_sev_ is the thresholds for those output targets
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // min_sev_ is the minimum (most verbose) of those levels, and is used
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //  as a short-circuit in the logging macros to identify messages that won't
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //  be logged.
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // ctx_sev_ is the minimum level at which file context is displayed
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static int min_sev_, dbg_sev_, ctx_sev_;
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // The output streams and their associated severities
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static StreamList streams_;
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Flags for formatting options
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static bool thread_, timestamp_;
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // The timestamp at which logging started.
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static uint32 start_;
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // are we in diagnostic mode (as defined by the app)?
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static bool is_diagnostic_mode_;
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DISALLOW_COPY_AND_ASSIGN(LogMessage);
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Logging Helpers
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass LogMultilineState {
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  size_t unprintable_count_[2];
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LogMultilineState() {
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    unprintable_count_[0] = unprintable_count_[1] = 0;
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// When possible, pass optional state variable to track various data across
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// multiple calls to LogMultiline.  Otherwise, pass NULL.
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid LogMultiline(LoggingSeverity level, const char* label, bool input,
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                  const void* data, size_t len, bool hex_mode,
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                  LogMultilineState* state);
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Macros which automatically disable logging when LOGGING == 0
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// If LOGGING is not explicitly defined, default to enabled in debug mode
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(SAFE_TO_DEFINE_TALK_BASE_LOGGING_MACROS)
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if !defined(LOGGING)
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(_DEBUG) && !defined(NDEBUG) && !defined(NO_LIBJINGLE_LOGGING)
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOGGING 1
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOGGING 0
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // !defined(LOGGING)
272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifndef LOG
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if LOGGING
275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// The following non-obvious technique for implementation of a
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// conditional log stream was stolen from google3/base/logging.h.
278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// This class is used to explicitly ignore values in the conditional
280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// logging macros.  This avoids compiler warnings like "value computed
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// is not used" and "statement has no effect".
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass LogMessageVoidify {
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LogMessageVoidify() { }
286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // This has to be an operator with a precedence lower than << but
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // higher than ?:
288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void operator&(std::ostream&) { }
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_SEVERITY_PRECONDITION(sev) \
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  !(talk_base::LogMessage::Loggable(sev)) \
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ? (void) 0 \
294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : talk_base::LogMessageVoidify() &
295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG(sev) \
297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_SEVERITY_PRECONDITION(talk_base::sev) \
298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev).stream()
299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// The _V version is for when a variable is passed in.  It doesn't do the
301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// namespace concatination.
302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_V(sev) \
303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_SEVERITY_PRECONDITION(sev) \
304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    talk_base::LogMessage(__FILE__, __LINE__, sev).stream()
305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// The _F version prefixes the message with the current function name.
307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(__GNUC__) && defined(_DEBUG)
308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_CHECK_LEVEL(sev) \
314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  talk_base::LogCheckLevel(talk_base::sev)
315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_CHECK_LEVEL_V(sev) \
316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  talk_base::LogCheckLevel(sev)
317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochinline bool LogCheckLevel(LoggingSeverity sev) {
318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return (LogMessage::GetMinLogSeverity() <= sev);
319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_E(sev, ctx, err, ...) \
322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_SEVERITY_PRECONDITION(talk_base::sev) \
323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \
324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                          talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \
325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        .stream()
326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else  // !LOGGING
328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Hopefully, the compiler will optimize away some of this code.
330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Note: syntax of "1 ? (void)0 : LogMessage" was causing errors in g++,
331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//   converted to "while (false)"
332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG(sev) \
333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (false)talk_base:: LogMessage(NULL, 0, talk_base::sev).stream()
334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_V(sev) \
335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (false) talk_base::LogMessage(NULL, 0, sev).stream()
336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_CHECK_LEVEL(sev) \
338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  false
339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_CHECK_LEVEL_V(sev) \
340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  false
341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_E(sev, ctx, err, ...) \
343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (false) talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \
344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                          talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \
345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      .stream()
346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // !LOGGING
348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_ERRNO_EX(sev, err) \
350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_E(sev, ERRNO, err)
351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_ERRNO(sev) \
352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_ERRNO_EX(sev, errno)
353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_GLE_EX(sev, err) \
356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_E(sev, HRESULT, err)
357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_GLE(sev) \
358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_GLE_EX(sev, GetLastError())
359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_GLEM(sev, mod) \
360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_E(sev, HRESULT, GetLastError(), mod)
361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_ERR_EX(sev, err) \
362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_GLE_EX(sev, err)
363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_ERR(sev) \
364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_GLE(sev)
365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LAST_SYSTEM_ERROR \
366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  (::GetLastError())
367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#elif POSIX
368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_ERR_EX(sev, err) \
369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_ERRNO_EX(sev, err)
370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LOG_ERR(sev) \
371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_ERRNO(sev)
372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define LAST_SYSTEM_ERROR \
373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  (errno)
374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define PLOG(sev, err) \
377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_ERR_EX(sev, err)
378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// TODO(?): Add an "assert" wrapper that logs in the same manner.
380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // LOG
382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // defined(SAFE_TO_DEFINE_TALK_BASE_LOGGING_MACROS)
383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}  // namespace talk_base
385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // TALK_BASE_LOGGING_H_
387