otsdaq-mu2e-stm  5.02.01
async_logger.cc
1 // Async logger header
2 #include "Mu2e-STMDAQ/utils/async_logger.hh"
3 
4 // Constructor
5 AsyncLogger::AsyncLogger(const Config& cfg, const std::shared_ptr<cpu_utils>& cpu_)
6  : done(false), cfg(cfg), cpu(cpu_)
7 {
8  // Get run start date and time
9  // auto t = std::time(nullptr);
10  // auto tm = *std::localtime(&t);
11  // std::ostringstream oss;
12  // oss << std::put_time(&tm,"%Y-%m-%d_%H-%M-%S");
13  std::string date_time = Timer::run_start_timestamp();
14 
15  // Get the log directory
16  std::string log_dir = EnvVars::expand("${LOG_DIR}");
17  // Get channel
18  std::string host = EnvVars::expand("${HOSTNAME}");
19  std::string channel = "LaBr";
20  if(host == cfg.getValue<std::string>("stm.ch0_host"))
21  channel = "HPGe";
22  // Get log file name
23  std::string log_file = cfg.getValue<std::string>("stm.write_data.logfile") + "_" +
24  channel + "_" + date_time + ".log";
25  // Get number alarms to store in SHM
26  size_t max_shm_alarms = cfg.getValue<int>("stm.dqm.max_num_alarms");
27  // Only make SHM if dqm on
28  bool make_shm = cfg.getValue<bool>("stm.operations.DQM");
29 
30  // LoggerSTM
31  LoggerSTM::Instance(LoggerSTM::DEBUG);
32  LoggerSTM::Instance()->setStylePlain();
33  LoggerSTM::Instance()->initSHM(make_shm, max_shm_alarms);
34  LoggerSTM::Instance()->LogToFile(log_dir + log_file);
35  LoggerSTM::Instance()->write(1, "STM DAQ started: " + date_time);
36  LoggerSTM::Instance()->write(1, "Loaded configuration file: " + cfg.getXMLpath());
37  LoggerSTM::Instance()->write(1, "LoggerSTM initialised");
38 
39  // Start thread to print to screen
40  printerThread = std::thread(&AsyncLogger::printerThreadFunc, this);
41 }
42 
43 // The printer thread function
44 void AsyncLogger::printerThreadFunc()
45 {
46  // Pin thread to core
47  cpu->get_next_core("AsyncLogger");
48 
49  // Inifinte loop
50  while(true)
51  {
52  // Mutex lock
53  std::unique_lock<std::mutex> lock(queueMutex);
54  cv.wait(lock, [this] { return !messageQueue.empty() || done; });
55 
56  // If a message is waiting...
57  while(!messageQueue.empty())
58  {
59  // Get next message from queue
60  Message msg = std::move(messageQueue.front());
61  messageQueue.pop();
62  // Unlock before printing to minimize mutex hold time
63  lock.unlock();
64  // Print message to screen (CHANGE TO LOGGER)
65  LoggerSTM::Instance()->write(msg.second, msg.first);
66  // std::cout << msg << std::endl;
67  // Reacquire lock for next iteration
68  lock.lock();
69  }
70 
71  // Exit thread if no more messages and done is set
72  if(done && messageQueue.empty())
73  {
74  break;
75  }
76  }
77 }
78 
79 // Function to log a message
80 void AsyncLogger::log(const std::string& msg, unsigned int level)
81 {
82  {
83  // Signal critical error asap
84  if(level == 0)
85  stop::trigger_critical_stop();
86 
87  // Lock the mutex
88  std::lock_guard<std::mutex> lock(queueMutex);
89 
90  // Get the current time
91  auto now = std::chrono::system_clock::now();
92  std::time_t now_c = std::chrono::system_clock::to_time_t(now);
93 
94  // Format the timestamp
95  std::ostringstream timeStream;
96  timeStream << std::put_time(std::localtime(&now_c), "%Y-%m-%d %H:%M:%S");
97 
98  // Construct the log message with the timestamp
99  std::string logEntry = "[" + timeStream.str() + "] " + msg;
100 
101  // Push the message to be printed to the queue
102  messageQueue.emplace(logEntry, level);
103  }
104  // Notify the printer thread
105  cv.notify_one();
106 }
Definition: config.hh:19