Code Monkey home page Code Monkey logo

spdmon's Introduction

spdmon

Progress monitor based on spdlog library. In just one function call visualize your loop progress!
It is simple, header-only library. Just copy spdmon.hpp file into you project and you are ready to go.
Main idea and algorithm is based on @epruesse progress monitor.

Usage

std::vector<int> vec {0,1,2,3,4,5,6,7,8,9};
for(auto [logger, val] : spdmon::LogProgress(vec))
{
    logger->info("Hi info");
    std::this_thread::sleep_for(500ms);
}
Progress logger: 100% |████████████████████████████| 250000/250000 [00:00:33 / 00:00:00]

It can also be executed with additional spdlog::logger containing many sinks.
In that case LoggerProgress will not include sinks writing logs to stdout when creating temporary logger.

std::vector<spdlog::sink_ptr> sinks;
sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_mt>());
sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>("logfile", true));
auto combined_logger = std::make_shared<spdlog::logger>("name", begin(sinks), end(sinks));

spdmon::LoggerProgress monitor(combined_logger, "Progress", 40);

Main features of LoggerProgress:

  • Allows you to use default logger to send logs from many threads
  • Works only on Linux platform
  • Works with latest spdlog library
  • Refactor code with Google C++ Style Guide
  • Works only with stdout
  • It is not using std::recursive_mutex
  • It does not require any modification of spdlog library. Logging sink is based on spdlog::sinks::ansicolor_sink

Benchmarks

Below are some benchmarks done in Ubuntu 64 bit, Intel i5-8250U CPU @ 3.4GHz. I have compared progress monitor to native spdlog::sinks::ansicolor_sink. Used spdlog benchmark code.

Synchronous mode

[info] **************************************************************
[info] Single thread, 250,000 iterations
[info] **************************************************************
[spdlog::ansicolor_stdout_sink_mt]  [info]                Elapsed: 6.93 secs            36,083/sec
[Progress logger]                   [info]                Elapsed: 19.55 secs           12,788/sec
[Progress logger + monitor]         [info]                Elapsed: 27.51 secs            9,086/sec
[info] **************************************************************
[info] 10 threads, competing over the same logger object, 250,000 iterations
[info] **************************************************************
[spdlog::ansicolor_stdout_sink_mt]  [info]                Elapsed: 7.00 secs            35,703/sec
[Progress logger]                   [info]                Elapsed: 21.73 secs           11,507/sec
[Progress logger + monitor]         [info]                Elapsed: 29.70 secs            8,416/sec

Example usage

/*
 * Example usage code
*/

#include <thread>
#include <future>
#include "spdlog/sinks/stdout_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdmon/spdmon.hpp"

int main()
{
  /*
   * Create logger with many sinks. It can include stdout sinks
  */
  std::vector<spdlog::sink_ptr> sinks;
  sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_mt>());
  sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>("logfile", true));
  auto combined_logger = std::make_shared<spdlog::logger>("name", begin(sinks), end(sinks));

  /*
   * Create progress logger. It checks for all stdout sinks and discard them
   * Instead of them it creates custom one, logging to stdout with progress bar
   * and makes it global default logger.
  */
  spdmon::LoggerProgress monitor(combined_logger, "Progress", 40);

  /* We can get newly created logger from progress logger to log new data */
  auto new_logger = monitor.GetLogger();
  new_logger->set_pattern("[thread %t] %+");
  new_logger->set_level(spdlog::level::trace);

  /*
   * We use lambda function to be passed to different logging threads
  */
  auto print_lambda = [&monitor, &new_logger](auto duration, int count) {
    for (int i = 0; i < count; i++)
    {
      spdlog::trace("Hi trace");
      spdlog::debug("Hi debug");
      spdlog::info("Hi info");
      new_logger->warn("Hi warn");
      new_logger->error("Hi err");
      new_logger->critical("Hi critical");

      ++monitor;

      std::this_thread::sleep_for(duration);
    }
  };

  using namespace std::chrono_literals;

  /*
   * Create few threads which will be logging data through progress logger
   * and global logger
  */
  std::vector<std::thread> threads;
  threads.push_back(std::thread{print_lambda, 250ms, 10});
  threads.push_back(std::thread{print_lambda, 750ms, 10});
  threads.push_back(std::thread{print_lambda, 350ms, 10});
  threads.push_back(std::thread{print_lambda, 500ms, 10});

  /*
   * Wait for threads to finish their jobs
  */
  for (auto &t : threads)
  {
    if (t.joinable())
      t.join();
  }

  return 0;
}

Authors

Huge thank you to Elmar Pruesse for the idea and starting this project!

spdmon's People

Contributors

jxi24 avatar michalber avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

spdmon's Issues

Nice work!

Thanks for starting this project! I always meant to separate the progress bar out of SINA - it was really just in there for convenience because I was lacking time.

Can you put me into the authors list here? The code is derived after all (I do recognise some of my lines). I'll toss the code out of SINA and use this instead. We can also drop the references to "SINA's progress monitor" I think.

Where there any features you dropped? IIRC I've got some code to log at larger intervals with regular lines if the sink isn't a terminal.

macOS/Windows support

Hi! I've always been interested in a spdlog-based progress bar for simple cli demos. This work looks great but the readme says it only supports Linux at the moment. Do you what what it would take to support macOS or Windows?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.