libqi  1.14.5
qi::log Developer Guide

go to the qi::log API reference.

Overview

New logs system

New logs goals are to improve and simplify how to use and read them.

Hierarchical Category

There is hierarchical category like in python. for example:

This allow easy log filtering. Add improve the readablilty into logs GUI.

Handlers

The default handler log to console. The color is enable on tty. The handler can be added or deleted. You just need to give a delegate to a log function with the following prototype:

void logfct(const qi::log::LogLevel verb,
            const char              *category,
            const char              *msg,
            const char              *file = "",
            const char              *fct = "",
            const int               line = 0);

Then you can add the handler with addLogHandler(name, fctLog)

addLogHandler("nameofloghandler", logfct);

and remove it with removeLogHandler(name).

addLogHandler("nameofloghandler");

Verbosity

There is now 7 logs levels that you can change using --log-level (-L) [log_level_number] option in order form 0 to 6:

Example printing only error and lower log levels:

$ ./a.out -L 2

Output:

I've just finished to log!
[FATAL] ...log.example.1: 41
[ERROR] ...log.example.1: 42
[FATAL] ...log.example.2: f4
[ERROR] ...log.example.2: e4
[FATAL] ...log.example.3: 21f4
[ERROR] ...log.example.3: 21e4
[ERROR] ...log.example.4: Where is nao? - Nao is in the kitchen. - How many are they? 42

Code Location

Code location is supported. You can get some information where is the logs call:

This is an option. You can get the location using --context (-c) on noaqi command line.

Example printing context logs:

$ ./a.out -c

Output:

I've just finished to log!
[FATAL] ...log.example.1: log_example.cpp(91) main 41
[ERROR] ...log.example.1: log_example.cpp(92) main 42
[WARN ] ...log.example.1: log_example.cpp(93) main 43
[INFO ] ...log.example.1: log_example.cpp(94) main 44
[FATAL] ...log.example.2: log_example.cpp(98) main f4
[ERROR] ...log.example.2: log_example.cpp(99) main e4
[WARN ] ...log.example.2: log_example.cpp(100) main w4
[INFO ] ...log.example.2: log_example.cpp(101) main i4
[FATAL] ...log.example.3: log_example.cpp(105) main 21f4
[ERROR] ...log.example.3: log_example.cpp(106) main 21e4
[WARN ] ...log.example.3: log_example.cpp(107) main 21w4
[INFO ] ...log.example.3: log_example.cpp(108) main 21i4
[WARN ] ...log.example.4: log_example.cpp(115) main Oups my buffer is too bad: badcafe
[ERROR] ...log.example.4: log_example.cpp(118) main Where is nao? - Nao is in the kitchen. - How many are they? 42
[INFO ] ...log.example.4: log_example.cpp(124) main 41 42 43 44

Asynchronous log

Log are asynchronous, we dont want to waste time in log, furthermore log can do networking. The handling of the log output is in a separated thread.

There is a way to disable asynchronous. Start naoqi with --synchronous-log command line option. Becarefull, it will slow down naoqi if you have lots of handlers.

Logs may be asynchronous, but they are actually being displayed in their request order.

Example printing synchronous logs:

$ ./a.out --synchronous-log

Output:

[FATAL] ...log.example.1: 41
[ERROR] ...log.example.1: 42
[WARN ] ...log.example.1: 43
[INFO ] ...log.example.1: 44
[FATAL] ...log.example.2: f4
[ERROR] ...log.example.2: e4
[WARN ] ...log.example.2: w4
[INFO ] ...log.example.2: i4
[FATAL] ...log.example.3: 21f4
[ERROR] ...log.example.3: 21e4
[WARN ] ...log.example.3: 21w4
[INFO ] ...log.example.3: 21i4
[WARN ] ...log.example.4: Oups my buffer is too bad: badcafe
[ERROR] ...log.example.4: Where is nao? - Nao is in the kitchen. - How many are they? 42
[INFO ] ...log.example.4: 41 42 43 44
I've just finished to log!

"I've just finished to log!" is print after everything else.

Compat

Options

Link

qi::log documentation.

Example

/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */
#include <qi/log.hpp>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

int main(int argc, char **argv)
{
  po::options_description desc("Allowed options");

  int globalVerbosity;

  // Used to parse options, as well as to put help message
  desc.add_options()
          ("help,h", "Produces help message")
          ("version", "Output NAOqi version.")
          ("verbose,v", "Set verbose verbosity.")
          ("debug,d", "Set debug verbosity.")
          ("quiet,q", "Do not show logs on console.")
          ("context,c", po::value<int>(), "Show context logs: [0-7] (0: none, 1: categories, 2: date, 3: file+line, 4: date+categories, 5: date+line+file, 6: categories+line+file, 7: all (date+categories+line+file+function)).")
          ("synchronous-log", "Activate synchronous logs.")
          ("log-level,L", po::value<int>(&globalVerbosity)->default_value(4), "Change the log minimum level: [0-6] (0: silent, 1: fatal, 2: error, 3: warning, 4: info, 5: verbose, 6: debug). Default: 4 (info)")
    ;

  // Map containing all the options with their values
  po::variables_map vm;

  // program option library throws all kind of errors, we just catch them
  // all, print usage and exit
  try
  {
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
  }
  catch (po::error &e)
  {
    std::cerr << e.what() << std::endl;
    std::cout << desc << std::endl;
    exit(1);
  }

  if (vm.count("help")) {
    std::cout << desc << std::endl;
    return 0;
  }

  // set default log verbosity
  qi::log::setVerbosity(qi::log::info);
  // set default log context
  qi::log::setContext(0);

  if (vm.count("log-level"))
  {
    if (globalVerbosity > 0 && globalVerbosity <= 6)
      qi::log::setVerbosity((qi::log::LogLevel)globalVerbosity);
    if (globalVerbosity > 6)
      qi::log::setVerbosity(qi::log::debug);
    if (globalVerbosity <= 0)
      qi::log::setVerbosity(qi::log::silent);
  }

  // Remove consoleloghandler (default log handler)
  if (vm.count("quiet"))
    qi::log::removeLogHandler("consoleloghandler");

  if (vm.count("debug"))
    qi::log::setVerbosity(qi::log::debug);

  if (vm.count("verbose"))
    qi::log::setVerbosity(qi::log::verbose);

  if (vm.count("context"))
  {
    int globalContext = vm["context"].as<int>();

    if (globalContext < 0)
    {
      qi::log::setContext(0);
    }
    else if (globalContext > 7)
    {
      qi::log::setContext(7);
    }
    else
    {
      qi::log::setContext(globalContext);
    }
  }

  if (vm.count("synchronous-log"))
    qi::log::setSynchronousLog(true);

  qiLogFatal("core.log.example.1", "%d\n", 41);
  qiLogError("core.log.example.1", "%d\n", 42);
  qiLogWarning("core.log.example.1", "%d\n", 43);
  qiLogInfo("core.log.example.1", "%d\n", 44);
  qiLogVerbose("core.log.example.1", "%d\n", 45);
  qiLogDebug("core.log.example.1", "%d\n", 46);

  qiLogFatal("core.log.example.2")   << "f" << 4 << std::endl;
  qiLogError("core.log.example.2")   << "e" << 4 << std::endl;
  qiLogWarning("core.log.example.2") << "w" << 4 << std::endl;
  qiLogInfo("core.log.example.2")    << "i" << 4 << std::endl;
  qiLogVerbose("core.log.example.2") << "v" << 4 << std::endl;
  qiLogDebug("core.log.example.2")   << "d" << 4 << std::endl;

  qiLogFatal("core.log.example.1", "without '\\n': %d", 41);
  qiLogError("core.log.example.1", "without '\\n': %d", 42);
  qiLogWarning("core.log.example.1", "without '\\n': %d", 43);
  qiLogInfo("core.log.example.1", "without '\\n': %d", 44);
  qiLogVerbose("core.log.example.1", "without '\\n': %d", 45);
  qiLogDebug("core.log.example.1", "without '\\n': %d", 46);
  qiLogFatal("core.log.example.1", "");
  qiLogFatal("core.log.example.1", "\n");

  qiLogFatal("core.log.example.2")   << "f " << "without '\\n'";
  qiLogError("core.log.example.2")   << "e " << "without '\\n'";
  qiLogWarning("core.log.example.2") << "w " << "without '\\n'";
  qiLogInfo("core.log.example.2")    << "i " << "without '\\n'";
  qiLogVerbose("core.log.example.2") << "v " << "without '\\n'";
  qiLogDebug("core.log.example.2")   << "d " << "without '\\n'";
  qiLogFatal("core.log.example.2")   << "";
  qiLogFatal("core.log.example.2")   << std::endl;

  qiLogFatal("core.log.example.3", "%d", 21)   << "f" << 4 << std::endl;
  qiLogError("core.log.example.3", "%d", 21)   << "e" << 4 << std::endl;
  qiLogWarning("core.log.example.3", "%d", 21) << "w" << 4 << std::endl;
  qiLogInfo("core.log.example.3", "%d", 21)    << "i" << 4 << std::endl;
  qiLogVerbose("core.log.example.3", "%d", 21) << "v" << 4 << std::endl;
  qiLogDebug("core.log.example.3", "%d", 21)   << "d" << 4 << std::endl;

  //c style
  qiLogWarning("core.log.example.4",
               "Oups my buffer is too bad: %x\n",
               0x0BADCAFE);

  //c++ style
  qiLogError("core.log.example.4") << "Where is nao?"
                                   << " - Nao is in the kitchen."
                                   << " - How many are they? "
                                   << 42 << std::endl;

  //mixup style
  qiLogInfo("core.log.example.4", "%d %d ", 41, 42) << 43 << " " << 44
                                                    << std::endl;

  std::cout << "I've just finished to log!" << std::endl;
}
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines