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



我正在尝试为我的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 时间戳。首先,我不知道我应该使用什么时间测量格式(我应该使用计时还是time_t类型?我正在尝试打印一个时间段,因此如果有持续时间的类型会很有帮助(我已经尝试过 chrono::d uration,但它似乎需要 C++11 支持(。其次,如果我知道要使用什么类型,如何将其打印到文件中?有没有办法将该类型转换为字符串?或者我可以将其直接传递给我的函数并以某种方式打印它吗?

在过去的几天里,这让我很困扰,我似乎无法弄清楚,所以任何输入都会非常有帮助。提前感谢!

获取 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::format("{0:%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::formatstd::formatter的规范。

截至 2020 年 12 月,还没有主要的编译器支持<format>库,因此您可以使用fmt,这是库的独立实现。

C++20 之前

考虑一下霍华德·欣南特(Howard Hinnant(的date图书馆,其中大部分作为chrono图书馆的新部分被并入C++20。在该库中找到的format函数使用与上面建议的 C++20 版本相同的语法,尽管没有与std::format集成。

记录:

如果 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和本地时间来自 ctime,https://en.cppreference.com/w/cpp/chrono/c/ctime

我通常使用我的实现来做这样的事情。

#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或以上。

如果你想要一个更手动的方法,这是我以前用过的

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);

然后只需将缓冲区(现在包含时间的字符串表示形式(输出到您的文件中。

最新更新