Skip to content

Commit fd1f7ae

Browse files
committed
added string option to library handle constructor
1 parent 7fea2b5 commit fd1f7ae

File tree

5 files changed

+157
-40
lines changed

5 files changed

+157
-40
lines changed

include/InfoLogger/InfoLogger.hxx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ class InfoLogger
138138
/// Constructor
139139
/// May throw exceptions on failure.
140140
InfoLogger();
141+
142+
// Constructor
143+
// with optional options
144+
// provided as a comma-separated list of key=value pairs
145+
InfoLogger(const std::string &options);
141146

142147
/// Destructor
143148
virtual ~InfoLogger();

src/InfoLogger.cxx

Lines changed: 146 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "infoLoggerMessage.h"
2121
#include "InfoLoggerClient.h"
22+
#include "infoLoggerUtils.h"
2223

2324
#include <stdio.h>
2425
#include <stdlib.h>
@@ -171,60 +172,105 @@ namespace AliceO2
171172
namespace InfoLogger
172173
{
173174

174-
int infoLoggerDWarningDone = 0;
175-
176175
// private class to isolate internal data from external interface
177176
class InfoLogger::Impl
178177
{
179178
public:
180-
Impl()
179+
Impl(const std::string &options)
181180
{
182181
// initiate internal members
183182
magicTag = InfoLoggerMagicNumber;
184183
numberOfMessages = 0;
185184
currentStreamMessage.clear();
186185
currentStreamOptions = undefinedMessageOption;
187-
186+
client = nullptr;
187+
188188
floodReset();
189189

190190
if (infoLog_proto_init()) {
191191
throw __LINE__;
192192
}
193193
refreshDefaultMsg();
194-
currentMode = OutputMode::infoLoggerD;
195-
196-
const char* confEnv = getenv("INFOLOGGER_MODE");
197-
if (confEnv != NULL) {
198-
if (!strcmp(confEnv, "stdout")) {
199-
currentMode = OutputMode::stdout;
200-
} else if (!strcmp(confEnv, "infoLoggerD")) {
201-
currentMode = OutputMode::infoLoggerD;
202-
} else if (!strncmp(confEnv, "file", 4)) {
203-
currentMode = OutputMode::file;
204-
const char* logFile = "./log.txt";
205-
if (confEnv[4] == ':') {
206-
logFile = &confEnv[5];
207-
}
208-
printf("Logging to file %s\n", logFile);
209-
stdLog.setLogFile(logFile);
210-
} else if (!strcmp(confEnv, "raw")) {
211-
currentMode = OutputMode::raw;
212-
} else if (!strcmp(confEnv, "none")) {
213-
currentMode = OutputMode::none; // useful for benchmarks
194+
195+
// option-processing routine
196+
auto processOptions = [&] (std::string opt) {
197+
std::map<std::string, std::string> kv;
198+
if (getKeyValuePairsFromString(opt, kv)) {
199+
throw __LINE__;
214200
}
201+
for (auto& it : kv) {
202+
if (it.first == "outputMode") {
203+
getOutputStreamFromString(it.second.c_str(), mainMode);
204+
} else if (it.first == "outputModeFallback") {
205+
getOutputStreamFromString(it.second.c_str(), fallbackMode);
206+
} else if (it.first == "verbose") {
207+
verbose = atoi(it.second.c_str());
208+
} else {
209+
// unknown option
210+
// printf("Unknown option %s\n",it.second.c_str());
211+
throw __LINE__;
212+
}
213+
}
214+
return;
215+
};
216+
217+
// parse options from constructor arg
218+
processOptions(options);
219+
220+
// parse options from environment
221+
const char* confEnvOptions = getenv("INFOLOGGER_OPTIONS");
222+
if (confEnvOptions != NULL) {
223+
processOptions(confEnvOptions);
215224
}
216-
client = nullptr;
217-
if (currentMode == OutputMode::infoLoggerD) {
218-
client = new InfoLoggerClient;
219-
if ((client == nullptr) || (!client->isOk())) {
220-
// fallback to stdout if infoLoggerD not available
221-
if (!infoLoggerDWarningDone) {
222-
infoLoggerDWarningDone = 1;
223-
//fprintf(stderr,"infoLoggerD not available, falling back to stdout logging\n");
224-
}
225-
currentMode = OutputMode::stdout;
225+
226+
const char* confEnvMode = getenv("INFOLOGGER_MODE");
227+
if (confEnvMode != NULL) {
228+
getOutputStreamFromString(confEnvMode, mainMode);
229+
}
230+
231+
// init main output and fallbacks if needed
232+
currentMode = mainMode;
233+
for (int it = 0; it < 3 ; it++) {
234+
if (it == 0) {
235+
currentMode = mainMode;
236+
} else if (it == 1) {
237+
currentMode = fallbackMode;
238+
} else {
239+
currentMode.mode = OutputMode::none;
240+
currentMode.path = "/dev/null";
241+
}
242+
if (verbose) {
243+
printf("Using output mode %s\n", getStringFromMode(currentMode.mode));
244+
}
245+
246+
if (currentMode.mode == OutputMode::file) {
247+
if (verbose) {
248+
printf("Logging to file %s\n", currentMode.path.c_str());
249+
}
250+
if (stdLog.setLogFile(currentMode.path.c_str(),0,4,0) == 0) {
251+
break;
252+
}
253+
} else if (currentMode.mode == OutputMode::stdout) {
254+
if (stdLog.setLogFile(nullptr) == 0) {
255+
break;
256+
}
257+
} else if (currentMode.mode == OutputMode::none) {
258+
if (stdLog.setLogFile(currentMode.path.c_str()) == 0) {
259+
break;
260+
}
261+
} else if (currentMode.mode == OutputMode::infoLoggerD) {
262+
client = new InfoLoggerClient;
263+
if (client != nullptr) {
264+
if (client->isOk()) {
265+
break;
266+
}
267+
}
268+
}
269+
if (verbose) {
270+
printf("Output to %s failed\n", getStringFromMode(currentMode.mode));
226271
}
227272
}
273+
228274
// todo
229275
// switch mode based on configuration / environment
230276
// connect to client only on first message (or try again after timeout)
@@ -258,8 +304,60 @@ class InfoLogger::Impl
258304
raw,
259305
none };
260306

261-
OutputMode currentMode; // current option for output
262-
307+
struct OutputStream {
308+
OutputMode mode; // selected mode
309+
std::string path; // optional path (eg for 'file' mode)
310+
};
311+
312+
// convert a string to a member of the OutputMode enum
313+
// and sets filePath in case of the "file" mode
314+
// throw an integer error code on error
315+
void getOutputStreamFromString(const char *s, OutputStream &out) {
316+
if (s == nullptr) {
317+
throw __LINE__;
318+
}
319+
out.mode = OutputMode::none;
320+
out.path = "";
321+
if (!strcmp(s,"stdout")) {
322+
out.mode = OutputMode::stdout;
323+
} else if (!strncmp(s,"file", 4)) {
324+
out.mode = OutputMode::file;
325+
if (s[4] == ':') {
326+
out.path = std::string(&s[5]);
327+
} else {
328+
out.path = "./log.txt";
329+
}
330+
} else if (!strcmp(s,"infoLoggerD")) {
331+
out.mode = OutputMode::infoLoggerD;
332+
} else if (!strcmp(s,"raw")) {
333+
out.mode = OutputMode::raw;
334+
} else if (!strcmp(s,"none")) {
335+
out.mode = OutputMode::none;
336+
} else {
337+
throw __LINE__;
338+
}
339+
return;
340+
};
341+
342+
const char* getStringFromMode(OutputMode m) {
343+
if (m==OutputMode::stdout) {
344+
return "stdout";
345+
} else if (m==OutputMode::file) {
346+
return "file";
347+
} else if (m==OutputMode::infoLoggerD) {
348+
return "infoLoggerD";
349+
} else if (m==OutputMode::none) {
350+
return "none";
351+
}
352+
return "unknown";
353+
}
354+
355+
OutputStream currentMode; // current option for output
356+
OutputStream mainMode = {OutputMode::infoLoggerD, ""}; // main output mode
357+
OutputStream fallbackMode = {OutputMode::stdout, ""}; // in case main mode is not available
358+
359+
bool verbose = 0; // in verbose mode, more info printed on stdout
360+
263361
/// Log a message, with a list of arguments of type va_list.
264362
/// \param message NUL-terminated string message to push to the log system. It uses the same format as specified for printf(), and the function accepts additionnal formatting parameters.
265363
/// \param ap Variable list of arguments (c.f. vprintf)
@@ -285,7 +383,7 @@ class InfoLogger::Impl
285383
void refreshDefaultMsg();
286384
infoLog_msg_t defaultMsg; //< default log message (in particular, to complete optionnal fields)
287385

288-
InfoLoggerClient* client; //< entity to communicate with local infoLoggerD
386+
InfoLoggerClient* client = nullptr; //< entity to communicate with local infoLoggerD
289387
SimpleLog stdLog; //< object to output messages to stdout/file
290388

291389
bool isRedirecting = false; // state of stdout/stderr redirection
@@ -561,7 +659,7 @@ int InfoLogger::Impl::pushMessage(const InfoLoggerMessageOption& options, const
561659
// on error, close connection / use stdout / buffer messages in memory ?
562660
}
563661

564-
if ((currentMode == OutputMode::stdout) || (currentMode == OutputMode::file)) {
662+
if ((currentMode.mode == OutputMode::stdout) || (currentMode.mode == OutputMode::file)) {
565663
char buffer[LOG_MAX_SIZE];
566664
msgHelper.MessageToText(&msg, buffer, sizeof(buffer), InfoLoggerMessageHelper::Format::Simple);
567665

@@ -582,7 +680,7 @@ int InfoLogger::Impl::pushMessage(const InfoLoggerMessageOption& options, const
582680
}
583681

584682
// raw output: infoLogger protocol to stdout
585-
if (currentMode == OutputMode::raw) {
683+
if (currentMode.mode == OutputMode::raw) {
586684
char buffer[LOG_MAX_SIZE];
587685
msgHelper.MessageToText(&msg, buffer, sizeof(buffer), InfoLoggerMessageHelper::Format::Encoded);
588686
puts(buffer);
@@ -625,7 +723,15 @@ int InfoLogger::Impl::logV(const InfoLoggerMessageOption& options, const InfoLog
625723

626724
InfoLogger::InfoLogger()
627725
{
628-
mPimpl = std::make_unique<InfoLogger::Impl>();
726+
mPimpl = std::make_unique<InfoLogger::Impl>("");
727+
if (mPimpl == NULL) {
728+
throw __LINE__;
729+
}
730+
}
731+
732+
InfoLogger::InfoLogger(const std::string &options)
733+
{
734+
mPimpl = std::make_unique<InfoLogger::Impl>(options);
629735
if (mPimpl == NULL) {
630736
throw __LINE__;
631737
}

src/InfoLoggerScripting.cxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ InfoLogger::InfoLogger()
2222
{
2323
logHandle = std::make_unique<baseInfoClass>();
2424
}
25+
InfoLogger::InfoLogger(const std::string &options)
26+
{
27+
logHandle = std::make_unique<baseInfoClass>(options);
28+
}
2529

2630
InfoLogger::~InfoLogger()
2731
{

src/InfoLoggerScripting.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class InfoLogger
7676
{
7777
public:
7878
InfoLogger();
79+
InfoLogger(const std::string &options);
7980
~InfoLogger();
8081

8182
// log with default metadata fields and specified severity

src/infoLogger.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class InfoLoggerMetadata {
4545
class InfoLogger {
4646
public:
4747
InfoLogger();
48+
InfoLogger(const std::string &message);
4849
~InfoLogger();
4950

5051
int logInfo(const std::string &message);

0 commit comments

Comments
 (0)