15#include <fairmq/Device.h>
16#include <fairmq/runDevice.h>
18#include "InfoLogger/InfoLogger.hxx"
23#include <unordered_map>
30#include <sys/inotify.h>
33using namespace AliceO2;
35static constexpr size_t MAX_LINES_FILE = 30;
36static constexpr size_t MAX_BYTES_FILE = MAX_LINES_FILE * 512;
37static constexpr size_t MAX_LINES_TOTAL = 1000;
38static constexpr size_t MAX_BYTES_TOTAL = MAX_LINES_TOTAL * 256;
53 printf(
"Monitoring file %s\n",
filename.c_str());
64 EPNMonitor(std::string
path,
bool infoLogger,
int runNumber, std::string partition);
70 void check_add_file(
const std::string&
filename);
71 void sendLog(
const std::string&
file,
const std::string&
message,
72 const InfoLogger::InfoLogger::Severity
severity = InfoLogger::InfoLogger::Severity::Error,
int level = 3);
74 bool mInfoLoggerActive;
75 volatile bool mTerminate =
false;
77 std::unordered_map<std::string, fileMon> mFiles;
79 std::vector<std::regex> mFilters;
80 std::unordered_map<std::string, std::pair<InfoLogger::InfoLogger::Severity, int>> mMapRootLogTypes;
81 volatile unsigned int mRunNumber;
82 std::string mPartition;
83 unsigned int nLines = 0;
84 unsigned int nBytes = 0;
85 std::unique_ptr<InfoLogger::InfoLogger> mLogger;
86 std::unique_ptr<InfoLogger::InfoLoggerContext> mLoggerContext;
91 mFilters.emplace_back(
"^Info in <");
92 mFilters.emplace_back(
"^Print in <");
93 mFilters.emplace_back(
"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{6}");
94 mFilters.emplace_back(
"^Warning in <Fit");
95 mFilters.emplace_back(
"^Warning in <TGraph");
96 mFilters.emplace_back(
"^Warning in <TInterpreter");
97 mFilters.emplace_back(
"Dividing histograms with different labels");
98 mMapRootLogTypes.emplace(
"Info in <", std::pair<InfoLogger::InfoLogger::Severity, int>{InfoLogger::InfoLogger::Severity::Info, 13});
99 mMapRootLogTypes.emplace(
"Print in <", std::pair<InfoLogger::InfoLogger::Severity, int>{InfoLogger::InfoLogger::Severity::Info, 13});
100 mMapRootLogTypes.emplace(
"Warning in <", std::pair<InfoLogger::InfoLogger::Severity, int>{InfoLogger::InfoLogger::Severity::Warning, 11});
101 mMapRootLogTypes.emplace(
"Error in <", std::pair<InfoLogger::InfoLogger::Severity, int>{InfoLogger::InfoLogger::Severity::Error, 2});
102 mMapRootLogTypes.emplace(
"Fatal in <", std::pair<InfoLogger::InfoLogger::Severity, int>{InfoLogger::InfoLogger::Severity::Fatal, 1});
103 mMapRootLogTypes.emplace(
"*** Break ***", std::pair<InfoLogger::InfoLogger::Severity, int>{InfoLogger::InfoLogger::Severity::Fatal, 1});
104 mInfoLoggerActive = infoLogger;
106 mRunNumber = runNumber;
107 mPartition = partition;
109 mLogger = std::make_unique<InfoLogger::InfoLogger>();
110 mLoggerContext = std::make_unique<InfoLogger::InfoLoggerContext>();
111 mLoggerContext->setField(InfoLogger::InfoLoggerContext::FieldName::Partition, partition !=
"" ? partition :
"unspecified");
112 mLoggerContext->setField(InfoLogger::InfoLoggerContext::FieldName::System, std::string(
"STDERR"));
114 mThread = std::thread(&EPNMonitor::thread,
this);
123void EPNMonitor::check_add_file(
const std::string&
filename)
126 static const std::regex match_stderr(
"_err\\.log$");
127 if (std::regex_search(
filename, match_stderr)) {
132void EPNMonitor::sendLog(
const std::string&
file,
const std::string&
message,
const InfoLogger::InfoLogger::Severity
severity,
int level)
134 if (mInfoLoggerActive) {
135 mLoggerContext->setField(InfoLogger::InfoLoggerContext::FieldName::Facility, (
"stderr/" +
file).substr(0, 31));
136 mLoggerContext->setField(InfoLogger::InfoLoggerContext::FieldName::Run, mRunNumber != 0 ?
std::to_string(mRunNumber) :
"unspecified");
137 static const InfoLogger::InfoLogger::InfoLoggerMessageOption opt = {
severity,
level, InfoLogger::InfoLogger::undefinedMessageOption.errorCode, InfoLogger::InfoLogger::undefinedMessageOption.sourceFile, InfoLogger::InfoLogger::undefinedMessageOption.sourceLine};
138 mLogger->log(opt, *mLoggerContext,
"stderr: %s",
file ==
"SYSLOG" ? (std::string(
"[GLOBAL SYSLOG]: ") +
message).c_str() :
message.c_str());
144void EPNMonitor::thread()
146 printf(
"EPN stderr Monitor active\n");
149 std::string syslogfile =
"/var/log/infologger_syslog";
151 file.open(syslogfile, std::ifstream::in);
153 mFiles.emplace(std::piecewise_construct, std::forward_as_tuple(syslogfile), std::forward_as_tuple(std::string(
"SYSLOG"), std::move(
file)));
159 static constexpr size_t BUFFER_SIZE = 64 * 1024;
160 std::vector<char> evt_buffer(BUFFER_SIZE);
161 std::vector<char> text_buffer(8192);
163 wd = inotify_add_watch(fd, mPath.c_str(), IN_CREATE);
167 pollfd pfd = {fd, POLLIN, 0};
169 for (
const auto&
entry :
std::filesystem::directory_iterator(mPath)) {
170 if (
entry.is_regular_file()) {
171 check_add_file(
entry.path().filename());
175 auto lastTime = std::chrono::system_clock::now();
176 while (!mTerminate) {
177 if (poll(&pfd, 1, 50) > 0) {
178 int l =
read(fd, evt_buffer.data(), BUFFER_SIZE);
180 throw std::runtime_error(std::string(
"Error waiting for inotify event ") +
std::to_string(l));
182 for (
int i = 0;
i < l;
i +=
sizeof(inotify_event)) {
183 inotify_event*
event = (inotify_event*)&evt_buffer[
i];
184 if (
event->len && (
event->mask & IN_CREATE) && !(
event->mask & IN_ISDIR)) {
185 check_add_file(
event->name);
190 auto curTime = std::chrono::system_clock::now();
191 if (std::chrono::duration_cast<std::chrono::milliseconds>(curTime - lastTime).
count() >= 1000) {
192 char*
ptr = text_buffer.data();
194 for (
auto fit = mFiles.begin();
fit != mFiles.end();
fit++) {
195 auto&
f =
fit->second;
202 std::getline(
file, line);
204 bool filterLine =
false;
205 for (
const auto&
filter : mFilters) {
206 if (std::regex_search(line,
filter)) {
215 auto severity{InfoLogger::InfoLogger::Severity::Error};
217 for (
const auto& logType : mMapRootLogTypes) {
218 if (line.find(logType.first) != std::string::npos) {
219 severity = std::get<InfoLogger::InfoLogger::Severity>(logType.second);
220 level = std::get<int>(logType.second);
225 f.nBytes += line.size();
227 nBytes += line.size();
228 if (
f.nLines >= MAX_LINES_FILE ||
f.nBytes >= MAX_BYTES_FILE) {
229 sendLog(
f.name,
"Exceeded log size for process " +
f.name +
" (" +
std::to_string(
f.nLines) +
" lines, " +
std::to_string(
f.nBytes) +
" bytes), not reporting any more errors from this file...");
233 if (nLines >= MAX_LINES_TOTAL || nBytes >= MAX_BYTES_TOTAL) {
238 }
while (!
file.eof());
242 if (nLines >= MAX_LINES_TOTAL || nBytes >= MAX_BYTES_TOTAL) {
243 sendLog(
"",
"Max total stderr log size exceeded (" +
std::to_string(nLines) +
" lines, " +
std::to_string(nBytes) +
"), not sending any more stderr logs from this node...");
250 inotify_rm_watch(fd, wd);
253 printf(
"EPN stderr Monitor terminating\n");
256static std::unique_ptr<EPNMonitor> gEPNMonitor;
263 std::string
path = getenv(
"DDS_LOCATION") ? (std::string(getenv(
"DDS_LOCATION")) +
"/") : std::string(
".");
264 bool infoLogger = fConfig->GetProperty<
int>(
"infologger");
267 std::string partition =
"";
269 partition = fConfig->GetProperty<std::string>(
"environment_id",
"");
270 printf(
"Got environment_id: %s\n", partition.c_str());
272 printf(
"Error getting environment_id\n");
275 gEPNMonitor = std::make_unique<EPNMonitor>(
path, infoLogger, 0, partition);
281 runNumber = atoi(fConfig->GetProperty<std::string>(
"runNumber",
"").c_str());
282 printf(
"Got runNumber: %d\n", runNumber);
284 printf(
"Error getting runNumber\n");
286 gEPNMonitor->setRunNr(runNumber);
297 options.add_options()(
"infologger", bpo::value<int>()->default_value(0),
"Send via infologger");
300std::unique_ptr<fair::mq::Device>
getDevice(fair::mq::ProgOptions& config)
302 return std::make_unique<EPNstderrMonitor>();
void addCustomOptions(bpo::options_description &options)
o2::devices::O2SimDevice * getDevice()
EPNMonitor(std::string path, bool infoLogger, int runNumber, std::string partition)
GLuint const GLchar * name
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLsizei const GLchar *const * path
GLuint GLsizei const GLchar * message
DeliveryType read(const std::string &str)
TFitResultPtr fit(const size_t nBins, const T *arr, const T xMin, const T xMax, TF1 &func, std::string_view option="")
Polygon< T > close(Polygon< T > polygon)
Defining DataPointCompositeObject explicitly as copiable.
std::string to_string(gsl::span< T, Size > span)
bool ConditionalRun() override
fileMon(const std::string &path, const std::string &filename)