Skip to content

packages/engine/scram-node/src/logger.h

Logging capability for various purposes, such as warnings and debugging. More...

Namespaces

Name
scram

Classes

Name
classscram::Logger <br>This is a general purpose logger; however, its main usage is asserted to be for debugging.
classscram::Timer <br>Automatic (scoped) timer to log process duration.

Defines

Name
TIME_STAMP() <br>Takes a current time stamp in nanoseconds.
CLOCK(var) <br>Starts the timing in nanoseconds.
DUR(var) <br>Calculates the time duration since the start of the clock in seconds.
TIMER(level, ...) <br>Creates an automatic unique logging timer for a scope.
LOG(level) <br>Logging with a level.
BLOG(level, cond) <br>Conditional logging with a level.

Detailed Description

Logging capability for various purposes, such as warnings and debugging.

This logging facility caters mostly developers. The design and code are inspired by the C++ logging framework of Petru Marginean, published at http://www.drdobbs.com/cpp/logging-in-c/201804215

The timing facilities are inspired by the talk of Bryce Adelstein "Benchmarking C++ Code" at CppCon 2015.

Macros Documentation

define TIME_STAMP

cpp
#define TIME_STAMP(
    
)
std::chrono::steady_clock::now().time_since_epoch().count()

Takes a current time stamp in nanoseconds.

define CLOCK

cpp
#define CLOCK(
    var
)
std::uint64_t var = TIME_STAMP()

Starts the timing in nanoseconds.

Parameters:

  • var A unique name for time variable in the scope.

define DUR

cpp
#define DUR(
    var
)
(TIME_STAMP() - var) * 1e-9

Calculates the time duration since the start of the clock in seconds.

Parameters:

  • var The variable initialized by the CLOCK macro (in the past!).

define TIMER

cpp
#define TIMER(
    level,
    ...
)
  Timer<level> BOOST_PP_CAT(timer_, __LINE__)(__VA_ARGS__)

Creates an automatic unique logging timer for a scope.

define LOG

cpp
#define LOG(
    level
)
  if (level <= scram::Logger::report_level()) scram::Logger().Get(level)

Logging with a level.

define BLOG

cpp
#define BLOG(
    level,
    cond
)
  if (cond) LOG(level)

Conditional logging with a level.

Source code

cpp
/*
 * Copyright (C) 2014-2018 Olzhas Rakhimov
 * Copyright (C) 2023 OpenPRA ORG Inc.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */


#pragma once

#include <cstdint>

#include <chrono>
#include <sstream>

#include <boost/noncopyable.hpp>
#include <boost/preprocessor/cat.hpp>

namespace scram {

#define TIME_STAMP() std::chrono::steady_clock::now().time_since_epoch().count()

#define CLOCK(var) std::uint64_t var = TIME_STAMP()

#define DUR(var) (TIME_STAMP() - var) * 1e-9

#define TIMER(level, ...) \
  Timer<level> BOOST_PP_CAT(timer_, __LINE__)(__VA_ARGS__)

// clang-format off
#define LOG(level) \
  if (level <= scram::Logger::report_level()) scram::Logger().Get(level)

#define BLOG(level, cond) \
  if (cond) LOG(level)
// clang-format on

enum LogLevel {  // The numbers are used for array indices.
  ERROR = 0,  
  WARNING,  
  INFO,  
  // Debugging logs are structured depending on the code under execution.
  // The deeper the code is located, the higher the level should be.
  // For example, if class A uses some utility class B,
  // class B should have higher debugging levels.
  // This is only a recommendation.
  DEBUG1,  
  DEBUG2,  
  DEBUG3,  
  DEBUG4,  
  DEBUG5  
};

const int kMaxVerbosity = 7;  

class Logger : private boost::noncopyable {
 public:
  ~Logger() noexcept;

  static LogLevel report_level() { return report_level_; }

  static void report_level(LogLevel level) { report_level_ = level; }

  std::ostringstream& Get(LogLevel level);

 private:
  static const char* const kLevelToString_[];

  static LogLevel report_level_;  

  std::ostringstream os_;  
};

template <LogLevel Level>
class Timer {
 public:
  explicit Timer(const char* process_name)
      : process_name_(process_name), process_time_(TIME_STAMP()) {
    LOG(Level) << process_name_ << "...";
  }

  ~Timer() {
    LOG(Level) << "Finished " << process_name_ << " in " << DUR(process_time_);
  }

 private:
  const char* process_name_;  
  std::uint64_t process_time_;  
};

}  // namespace scram

Updated on 2025-11-11 at 16:51:08 +0000