Чтение и запись журнала на определенный промежуток времени с ++ - PullRequest
0 голосов
/ 28 мая 2018

Я хочу записать в файл журнала отметку времени.Временная метка должна представлять временной интервал с начала приложения, как показано ниже:

1: это сообщение журнала поступило через 1 с после запуска приложения

5: это сообщение журнала поступило через 5 сзапуска приложения

Затем я хочу прочитать сообщение журнала в этот точный интервал времени.Например, после 1 с я прочитаю первое сообщение, затем, когда пройдет 5 с, я прочитаю второе сообщение.

Есть ли какая-нибудь библиотека, с помощью которой я могу это сделать?Я нашел некоторую библиотеку, например easyloggingcpp , которая может сохранять файл журнала, используя метку времени.Но отметка времени соответствует времени.Также я не нашел способа прочитать сообщение за определенный промежуток времени.

Есть ли способ, которым я могу это сделать?

Ответы [ 4 ]

0 голосов
/ 28 мая 2018

Таким образом, вам нужен класс ведения журнала в производителе, который будет знать время запуска приложения.

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;
}
0 голосов
/ 28 мая 2018

Вы можете использовать библиотеку 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() << "s\n";

    // 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() << "s\n";

}

Для обмена сообщениями журнала речь идет только о записи в файл.,Таким образом, вы можете создать свой собственный класс Logger и написать специфический для него парсер, чтобы читать сообщения за определенный промежуток времени.Другой вариант будет использовать easyloggingcpp , как вы сказали.Вы можете найти конкретный пример здесь

0 голосов
/ 28 мая 2018

У меня есть простое демонстрационное приложение для этого.Я использую 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("waiting\n");

    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 (секунды с 01 января 1970 года).

будет производить что-то вроде этого:

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.
0 голосов
/ 28 мая 2018

Глобальные переменные гарантированно инициализируются до запуска main.

Итак, сначала создайте глобальную const переменную app_start_time, инициализированную значением

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

Затем в *Функция 1008 * использует следующий код для подсчета секунд:

auto time_since_start = std::chrono::system_clock::now() - app_start_time;
auto seconds_since_start= std::chrono::seconds(time_since_start).count();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...