mpacklog — Log dictionaries to file using MessagePack  v2.1.0
Logger.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 Stéphane Caron
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * This file incorporates work covered by the following copyright and
17  * permission notice:
18  *
19  * Logger class of mc_rtc
20  * Copyright 2015-2019 CNRS-UM LIRMM, CNRS-AIST JRL
21  * License: BSD-2-Clause (see licenses/LICENSE-mc_rtc)
22  */
23 
24 #include "mpacklog/cpp/Logger.h"
25 
26 #include <string>
27 
28 namespace mpacklog {
29 
30 Logger::Logger(const std::string &path, bool append) {
31  auto flags = std::ofstream::binary;
32  if (append) {
33  flags |= std::ofstream::app;
34  }
35  file_.open(path, flags);
36  if (!file_) {
37  throw std::runtime_error("Cannot open " + path + " for writing");
38  }
39  thread_ = std::thread([this]() {
40 #ifdef __APPLE__
41  pthread_setname_np("logger_thread");
42 #else
43  pthread_setname_np(pthread_self(), "logger_thread");
44 #endif
45  while (keep_going_) {
46  flush_buffer();
47 
48  // The sleep duration doesn't have a big influence, no need to wake up
49  // too often. This value assumes a > 1 ms long control period.
50  std::this_thread::sleep_for(std::chrono::microseconds(100));
51  }
52  flush_buffer();
53  });
54 }
55 
57  keep_going_ = false;
58  if (thread_.joinable()) {
59  thread_.join();
60  }
61  file_.close();
62 }
63 
64 bool Logger::put(char *data, size_t size) {
65  last_size_ = size;
66  char *ndata = new char[size];
67  std::memcpy(ndata, data, size);
68  return circular_buffer_.push({ndata, size});
69 }
70 
71 void Logger::flush_buffer() {
72  while (circular_buffer_.pop(pop_)) {
73  char *data = pop_.first;
74  size_t size = pop_.second;
75  file_.write(data, static_cast<int>(size));
76  delete[] data;
77 
78  // Also flush the output stream, otherwise buffering tends to increase
79  // variance / cause spikes in consumer loop rates.
80  file_.flush();
81  }
82 }
83 
84 } // namespace mpacklog
mpacklog::CircularBuffer::push
bool push(const T &item)
Push data to the buffer.
Definition: CircularBuffer.h:57
mpacklog::Logger::~Logger
~Logger()
Stop the logging thread.
Definition: Logger.cpp:56
mpacklog
Log action and observation dictionaries to MessagePack binary files.
Definition: CircularBuffer.h:30
mpacklog::Logger::Logger
Logger(const std::string &path, bool append=false)
Open a new log file and start the logging thread.
Definition: Logger.cpp:30
mpacklog::CircularBuffer::pop
bool pop(T &item)
Pop next item from the buffer.
Definition: CircularBuffer.h:74
Logger.h
mpacklog::Logger::put
bool put(char *data, size_t size)
Save data to be written to the log.
Definition: Logger.cpp:64