blob: 9b898249020158c77cea0cedc0489c7b25269806 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_LIB_SYSTEM_MONITOR_GT_LOG_H_
#define GARNET_LIB_SYSTEM_MONITOR_GT_LOG_H_
#include <cassert>
#include <fstream>
#include <iostream>
#include <sstream>
// TODO(sm_bug.com/48): This is a minimum logging system intended to quickly
// replace a prior logging API. This should be expanded over time.
// Each level will be tagged in the output. Output from levels can be enabled or
// disabled by ordinal value.
// This is defined outside of the namespace for user ergonomics.
enum class GuiToolsLogLevel : int {
DEBUG3 = -3,
DEBUG2 = -2,
DEBUG = -1,
INFO = 0,
WARNING = 1,
ERROR = 2,
FATAL = 3,
};
namespace gt {
extern GuiToolsLogLevel g_log_level;
extern std::ofstream g_no_output_ofstream;
class Logger {
public:
// Write the line prefix.
// Note: |out| and |file_path| must not be null.
Logger(std::ostream* out, GuiToolsLogLevel level, GuiToolsLogLevel limit,
const char* file_path, int line, const char* function)
: out_(out) {
assert(out != nullptr);
assert(file_path != nullptr);
if (level < limit) {
out_ = &g_no_output_ofstream;
return;
}
switch (level) {
case GuiToolsLogLevel::FATAL:
*out_ << "[FATAL]";
break;
case GuiToolsLogLevel::ERROR:
*out_ << "[ERROR]";
break;
case GuiToolsLogLevel::WARNING:
*out_ << "[WARNING]";
break;
case GuiToolsLogLevel::INFO:
*out_ << "[INFO]";
break;
case GuiToolsLogLevel::DEBUG:
*out_ << "[DEBUG]";
break;
case GuiToolsLogLevel::DEBUG2:
*out_ << "[DEBUG2]";
break;
case GuiToolsLogLevel::DEBUG3:
*out_ << "[DEBUG3]";
break;
default:
*out_ << "[UNKNOWN]";
break;
}
*out_ << NameOnly(file_path) << ":" << line << ": " << function << ": ";
}
// Put an end-line on the output.
~Logger() { *out_ << std::endl; }
// A stream for the log output for the caller to use.
std::ostream& out() { return *out_; }
private:
std::ostream* out_;
// Clip the name off the path. (It's too noisy to print a long file path on
// each log line.)
const char* NameOnly(const char* file_path) {
const char* name = strrchr(file_path, '/');
return name ? name + 1 : file_path;
}
};
// Initialize the logging systems. The parameters are similar to those passed to
// main().
// Returns true on success.
bool SetUpLogging(int argc, const char* const* argv);
// Provides an ostream to send output to. Avoid calling this function directly.
// Use the GT_LOG macro provided below.
inline std::ostream& GuiToolsLog(GuiToolsLogLevel level) { return std::cout; }
} // namespace gt.
// Use like you would `std::cout`. E.g.
// GT_LOG(INFO) << "The special value is " << special_value;
//
// A new-line will end each call implicitly. (If std::endl is passed, there will
// be two '\n' printed.)
#define GT_LOG(x) \
::gt::Logger(&std::cout, GuiToolsLogLevel::x, ::gt::g_log_level, __FILE__, \
__LINE__, __FUNCTION__) \
.out()
#endif // GARNET_LIB_SYSTEM_MONITOR_GT_LOG_H_