特定时间间隔 C++ 上的读写日志

Read & write log on specific time interval c++

本文关键字:读写 日志 C++ 定时间      更新时间:2023-10-16

我想写入带有时间戳的日志文件。时间戳应表示从应用程序开始的时间间隔,如下所示:

1

:此日志消息在启动应用程序 1 秒后到达

5:此日志消息在启动应用程序 5 秒后到达

然后我想在该确切的时间间隔内读取日志消息。就像在 1s 之后,我将阅读第一条消息,然后当 5s 通过时,我将阅读第二条消息。

有没有可以做到这一点的库?我找到了一些像easyloggingcpp这样的库,它可以使用时间戳保存日志文件。但时间戳是相应的时间。我也没有找到任何方法如何在特定的时间间隔内阅读消息。

有什么办法可以做到吗?

因此,您需要在生产者中有一个能够识别应用程序启动时间的日志记录类。

class Logger {
static std::chrono::steady_clock::time_point start; // program start
std::ofstream out;                                  // log file stream
public:
Logger(const char *filename): out(filename) {}
void log(const char *msg) {                         // log function
std::chrono::steady_clock::time_point cur = std::chrono::steady_clock::now();
std::chrono::duration<double> d = cur - start;  // delta time since program start
// prepend text message with delta time
out << int(d.count()) << " - " << msg << std::endl;
}
~Logger() {
out.close();
}
};

以下部分是一个定义规则定义,该定义应在程序中恰好出现一次。即使类的定义在包含文件中,也应该将其写入主源代码

// definition of static member
std::chrono::steady_clock::time_point Logger::start = std::chrono::steady_clock::now();

您可以简单地在生产者程序中使用它:

int main() {
Logger log("foo.log");
std::chrono::duration<int> d = std::chrono::duration<int>(1);
// sleep for 1 second
std::this_thread::sleep_for(d);
log.log("After 1s");
// sleep for 4 seconds more
d = std::chrono::duration<int>(4);
std::this_thread::sleep_for(d);
log.log("After 5s");
return 0;
}

然后,您需要一个读取器从日志文件中读取每一行,从开头提取延迟,并从最后一条消息开始计算延迟(从开始的延迟随着构造而增加(,并在这段时间内休眠:

int main() {
std::ifstream in("foo.log");           // log file input stream
// store program start time
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
std::string line;
while (std::getline(in, line)) {       // read log file one line at a time
std::stringstream ss(line);        // parse line to extract delay
int delay;
if (! (ss >> delay)) break;
std::chrono::duration<int> d(delay);
std::this_thread::sleep_until(start + d); // wait until approriate time
// message processing (here simple display on stdout)
std::cout << line << std::endl;
}
return 0;
}

您可以使用std::chrono库来实现时间目的。你基本上在代码的开头获取时间并将其保存在变量中。之后,您可以在需要时间间隔时获取当前时间,并找到以前和当前时间之间的差异,如下所示。

#include <iostream>
#include <chrono>
#include <ctime>

int main()
{
auto start = std::chrono::system_clock::now();
// Some time consuming operations ... 
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;   
std::cout << "elapsed time: " << elapsed_seconds.count() << "sn";
// Some another time consuming operations ... 
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;   
std::cout << "elapsed time: " << elapsed_seconds.count() << "sn";
}

对于日志消息传递,它只是写入文件。因此,您可以创建自定义Logger类并编写特定于它的解析器,以便按特定时间间隔读取消息。另一种选择是使用您所说的easyloggingcpp。您可以在此处找到具体示例

全局变量保证在运行 main 之前初始化。

所以首先创建一个全局const变量app_start_time用值初始化

const auto app_start_time = std::chrono::system_clock::now();

然后在log函数中使用以下代码计算秒数:

auto time_since_start = std::chrono::system_clock::now() - app_start_time;
auto seconds_since_start= std::chrono::seconds(time_since_start).count();

我有一个简单的演示应用程序。我使用ctime获取时间戳std::time(0)这段代码不应该被重用,它使用简单的队列(不是线程安全的(,只是为了让它变得简单演示。

#include <iostream>     // std::cout
#include <thread>       // std::thread
#include <cstdio>       // printf, scanf, puts, NULL
#include <cstdlib>      // srand, rand
#include <ctime>        // time
#include <chrono>       // std::chrono::seconds, std::this_thread::sleep_for
#include <queue>        // std::ueue
std::queue<int> queue;
void producer() {
srand(time(NULL));
while (1) {
int message = rand();
queue.push(message);
int sleep = rand() % 5;
std::this_thread::sleep_for(std::chrono::seconds(sleep));
}
}
void consumer()
{
int start_time = std::time(0);
while(1) {
printf("waitingn");
while (queue.empty()); // busy waiting
int timestamp = std::time(0);
int message = queue.front();
int arrival_time_from_start = (timestamp - start_time);
queue.pop();
printf("message %d arrive at %d (unix timestamp), %d second after app start.n", message, timestamp, arrival_time_from_start);
}  
}
int main() 
{
std::thread first(producer);
std::thread second(consumer);
first.join();                // pauses until first finishes
second.join();               // pauses until second finishes
return 0;
}

生产者线程产生一些整数来queue,然后等待随机秒 [0-5]。然后是消费线程,等待queue填满。当queue填满时,它会消耗(queue.pop()(并使用其unix时间戳(自1970年1月1日以来的秒数(打印到屏幕上。

它将产生如下内容:

waiting
message 1611033160 arrive at 1527496314 (unix timestamp), 0 second after app start.
waiting
message 1055908354 arrive at 1527496318 (unix timestamp), 4 second after app start.
waiting
message 788236843 arrive at 1527496320 (unix timestamp), 6 second after app start.
waiting
message 1849353197 arrive at 1527496323 (unix timestamp), 9 second after app start.
waiting
message 62004690 arrive at 1527496326 (unix timestamp), 12 second after app start.
waiting
message 1668815337 arrive at 1527496326 (unix timestamp), 12 second after app start.
waiting
message 533376047 arrive at 1527496330 (unix timestamp), 16 second after app start.