如何将消息时间戳记写入日志文件?

时间:2018-10-09 20:37:16

标签: c++ logging time timestamp chrono

我正在尝试为C ++程序创建一个日志文件。我的目标是在程序的两点放置两个时间戳,并在文件中打印这两点之间的CPU时间周期。我这样做是因为我想知道代码的哪些部分最耗时,因此可以进行改进(因此可能要测量几块代码)。到目前为止,我已经制作了一个函数,该函数在被调用时将作为参数传递的字符串打印到文件中:

#define LOGFILE "myprog.log"
void Log (std::string message){
    std::ofstream ofs;
    ofs.open(LOGFILE, std::ofstream::out | std::ios::app);
    ofs << message << std::endl;
    ofs.close();
}

但是,我很难弄清楚如何打印CPU时间戳。首先,我不知道应该使用哪种时间测量格式(我应该使用chrono还是time_t类型?)我正在尝试打印时间段,因此如果存在持续时间类型,这会有所帮助(我我尝试了chrono :: duration,但似乎需要C ++ 11支持)。其次,鉴于我知道要使用哪种类型,如何将其打印到文件中?有没有一种方法可以将该类型转换为字符串?还是可以将其直接传递给函数并以某种方式打印?

最近几天这让我很烦恼,而且我似乎无法弄清楚,因此任何输入都会非常有帮助。预先感谢!

4 个答案:

答案 0 :(得分:4)

获取CPU时间戳

您将要使用std::chrono::system_clock来获取此时间戳。 请勿使用std::chrono::steady_clockstd::chrono::high_resolution_clock ,因为它们是用于进行高精度计时测量的,因此不保证保真度或对壁钟时间的准确性。

auto now = std::chrono::system_clock::now();
//now is a time_point object describing the instant it was recorded according to your system clock

以可读格式打印此CPU时间戳记

在C ++ 20中,这很简单。

std::string formatted_time = std::chrono::format("%F_%T", now);
ofs << formatted_time << ": " << message << std::endl;
  • %F替代%Y-%m-%D,后者将以ISO格式(即2018-10-09)输出年月日。
  • %T%H:%M:%S相同,它将输出一个时间,即17:55:34.786

有关更多选项/详情,请参见std::chrono::format的规范。

C ++ 20之前的版本

考虑Howard Hinnant's date library,其中大多数已作为chrono库的新部分并入C ++ 20。该库中的format函数使用与上述C ++ 20版本相同的语法。

答案 1 :(得分:1)

我通常将自己的实现用于此类事情。

#include <chrono>
#include <ctime>


// strftime format
#define LOGGER_PRETTY_TIME_FORMAT "%Y-%m-%d %H:%M:%S"

// printf format
#define LOGGER_PRETTY_MS_FORMAT ".%03d"


// convert current time to milliseconds since unix epoch
template <typename T>
static int to_ms(const std::chrono::time_point<T>& tp)
{
    using namespace std::chrono;

    auto dur = tp.time_since_epoch();
    return static_cast<int>(duration_cast<milliseconds>(dur).count());
}


// format it in two parts: main part with date and time and part with milliseconds
static std::string pretty_time()
{
    auto tp = std::chrono::system_clock::now();
    std::time_t current_time = std::chrono::system_clock::to_time_t(tp);

    // this function use static global pointer. so it is not thread safe solution
    std::tm* time_info = std::localtime(&current_time);

    char buffer[128];

    int string_size = strftime(
        buffer, sizeof(buffer),
        LOGGER_PRETTY_TIME_FORMAT,
        time_info
    );

    int ms = to_ms(tp) % 1000;

    string_size += std::snprintf(
        buffer + string_size, sizeof(buffer) - string_size,
        LOGGER_PRETTY_MS_FORMAT, ms
    );

    return std::string(buffer, buffer + string_size);
}

它以2018-09-23 21:58:52.642格式返回当前时间。

是的,它要求--std=c++11或更高。

答案 2 :(得分:1)

作记录:

如果像我一样C ++ 20功能不可用,则可以使用以下功能:

#include <ctime>
#include <iomanip>
#include <iostream>

using namespace std ;

time_t now = time(nullptr) ;
cout << put_time(localtime(&now), "%T") << endl ;

put_time在iomanip库中定义,请查看https://en.cppreference.com/w/cpp/io/manip/put_time,并且time_t和localtime来自ctime https://en.cppreference.com/w/cpp/chrono/c/ctime

答案 3 :(得分:0)

如果您想要更手动的方法,这就是我以前使用的

char buffer[MAX_BUFFER_SIZE];

time_t t = time(NULL);
struct tm *lt = localtime(&t);

snprintf(buffer, MAX_BUFFER_SIZE, "%02d/%02d/%02d %02d:%02d:%02d", lt->tm_mon+1, lt->tm_mday, lt->tm_year%100, lt->tm_hour, lt->tm_min, lt->tm_sec);

然后仅将 buffer 输出到文件中,该缓冲区现在包含时间的字符串表示形式。