blob: d9c02fe90919ea9abfa70b824cc9ac58a020253e [file] [log] [blame]
/*
* Copyright (C) 2004-2021 Savoir-faire Linux Inc.
*
* Author: Julien Bonjean <julien.bonjean@savoirfairelinux.com>
* Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
//#define __STDC_FORMAT_MACROS 1
#include <cinttypes> // for PRIx64
#include <cstdarg>
#include <atomic>
#include <sstream>
#include <string>
#include "string_utils.h" // to_string
#ifdef __cplusplus
extern "C" {
#endif
/**
* Thread-safe function to print the stringified contents of errno
*/
void strErr();
#ifdef __cplusplus
}
#endif
#ifdef __ANDROID__
#include <android/log.h>
#define LOG_ERR ANDROID_LOG_ERROR
#define LOG_WARNING ANDROID_LOG_WARN
#define LOG_INFO ANDROID_LOG_INFO
#define LOG_DEBUG ANDROID_LOG_DEBUG
#elif defined(_WIN32)
#include "winsyslog.h"
#define LOG_ERR EVENTLOG_ERROR_TYPE
#define LOG_WARNING EVENTLOG_WARNING_TYPE
#define LOG_INFO EVENTLOG_INFORMATION_TYPE
#define LOG_DEBUG EVENTLOG_SUCCESS
#else
#include <syslog.h> // Defines LOG_XXXX
#endif /* __ANDROID__ / _WIN32 */
#if defined(_WIN32) && !defined(_MSC_VER)
#define PRINTF_ATTRIBUTE(a, b) __attribute__((format(gnu_printf, a, b)))
#elif defined(__GNUC__)
#define PRINTF_ATTRIBUTE(a, b) __attribute__((format(printf, a, b)))
#else
#define PRINTF_ATTRIBUTE(a, b)
#endif
namespace jami {
///
/// Level-driven logging class that support printf and C++ stream logging fashions.
///
class Logger
{
public:
class Handler;
struct Msg;
Logger(int level, const char* file, int line, bool linefeed)
: level_ {level}
, file_ {file}
, line_ {line}
, linefeed_ {linefeed}
{}
Logger() = delete;
Logger(const Logger&) = delete;
Logger(Logger&&) = default;
~Logger() { log(level_, file_, line_, linefeed_, "%s", os_.str().c_str()); }
template<typename T>
inline Logger& operator<<(const T& value)
{
os_ << value;
return *this;
}
///
/// Printf fashion logging.
///
/// Example: JAMI_DBG("%s", "Hello, World!")
///
static void log(int level, const char* file, int line, bool linefeed, const char* const fmt, ...)
PRINTF_ATTRIBUTE(5, 6);
///
/// Printf fashion logging (using va_list parameters)
///
static void vlog(int level, const char* file, int line, bool linefeed, const char* fmt, va_list);
static void setConsoleLog(bool enable);
static void setSysLog(bool enable);
static void setMonitorLog(bool enable);
static void setFileLog(const std::string& path);
static void setDebugMode(bool enable);
static void fini();
///
/// Stream fashion logging.
///
/// Example: JAMI_DBG() << "Hello, World!"
///
static Logger log(int level, const char* file, int line, bool linefeed)
{
return {level, file, line, linefeed};
}
private:
int level_; ///< LOG_XXXX values
const char* const file_; ///< contextual filename (printed as header)
const int line_; ///< contextual line number (printed as header)
bool linefeed_ {
true}; ///< true if a '\n' (or any platform equivalent) has to be put at line end in consoleMode
std::ostringstream os_; ///< string stream used with C++ stream style (stream operator<<)
};
// We need to use macros for contextual information
#define JAMI_INFO(...) ::jami::Logger::log(LOG_INFO, __FILE__, __LINE__, true, ##__VA_ARGS__)
#define JAMI_DBG(...) ::jami::Logger::log(LOG_DEBUG, __FILE__, __LINE__, true, ##__VA_ARGS__)
#define JAMI_WARN(...) ::jami::Logger::log(LOG_WARNING, __FILE__, __LINE__, true, ##__VA_ARGS__)
#define JAMI_ERR(...) ::jami::Logger::log(LOG_ERR, __FILE__, __LINE__, true, ##__VA_ARGS__)
#define JAMI_XINFO(...) ::jami::Logger::log(LOG_INFO, __FILE__, __LINE__, false, ##__VA_ARGS__)
#define JAMI_XDBG(...) ::jami::Logger::log(LOG_DEBUG, __FILE__, __LINE__, false, ##__VA_ARGS__)
#define JAMI_XWARN(...) ::jami::Logger::log(LOG_WARNING, __FILE__, __LINE__, false, ##__VA_ARGS__)
#define JAMI_XERR(...) ::jami::Logger::log(LOG_ERR, __FILE__, __LINE__, false, ##__VA_ARGS__)
} // namespace jami