fault/fm-common/sources/fmLog.cpp
fperez f8716aa344 Add "proposed_repair_action" attr to event log file
Even when event logs have this attribute available, it is not being
logged in the /var/log/fm-event.log file. This could result in a lack
of certain information for external tools that use it.

Test Plan:
PASS: Build fm-common package and install it. Then, trigger an alarm
      with 'proposed_repair_action'. Verify its presence in the
      /var/log/fm-event.log
PASS: Raise an alarm without 'proposed_repair_action'. Check that
      the empty attribute is present.
PASS: Raise an alarm with a long 'proposed_repair_action'. verify that
      this message is not affecting other attributes.

Closes-Bug: 2042579

Change-Id: Ic27b840041872c3afd0be28e11556acf42a3d5a9
Signed-off-by: fperez <fabrizio.perez@windriver.com>
2023-11-02 19:07:49 +00:00

177 lines
5.4 KiB
C++

//
// Copyright (c) 2014-2018, 2023 Wind River Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <syslog.h>
#include "fmLog.h"
#include "fmDbAlarm.h"
#include "fmDbEventLog.h"
#include "fmConfig.h"
#include "fmConstants.h"
static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static char * escape_json(const char * s, char * buffer, const int bufLen);
void fmLoggingInit() {
static bool has_inited=false;
if (!has_inited){
openlog(NULL,LOG_CONS | LOG_NDELAY,LOG_LOCAL1);
setlogmask(LOG_UPTO (LOG_INFO));
}
std::string val;
std::string key = FM_DEBUG_FLAG;
if ((fm_get_config_key(key, val)) && (val.compare("True") == 0)){
setlogmask(LOG_UPTO (LOG_DEBUG));
} else {
setlogmask(LOG_UPTO (LOG_INFO));
}
has_inited=true;
}
void fmLogMsg(int level, const char *data,...){
va_list ap;
va_start(ap, data);
vsyslog(level,data,ap);
va_end(ap);
}
// formats event into json form for logging
static char * formattedEvent(CFmDbEventLog::data_type event_map, char * output, int outputSize) {
int bufLen = 1024;
char * buffer = (char *) malloc(bufLen);
int outputLen = 0;
snprintf(output + outputLen, outputSize - outputLen, "{ \"%s\" : \"%s\", ", "event_log_id", escape_json(event_map["event_log_id"].c_str(), buffer, bufLen));
outputLen = strlen(output);
snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "reason_text", escape_json(event_map["reason_text"].c_str(), buffer, bufLen));
outputLen = strlen(output);
snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "entity_instance_id", escape_json(event_map["entity_instance_id"].c_str(), buffer, bufLen));
outputLen = strlen(output);
snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "severity", escape_json(event_map["severity"].c_str(), buffer, bufLen));
outputLen = strlen(output);
snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "state", escape_json(event_map["state"].c_str(), buffer, bufLen));
outputLen = strlen(output);
snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "proposed_repair_action", escape_json(event_map["proposed_repair_action"].c_str(), buffer, bufLen));
outputLen = strlen(output);
snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\" }", "timestamp", escape_json(event_map["timestamp"].c_str(), buffer, bufLen));
free(buffer);
return output;
}
// logs event to syslog
void fmLogEVT(int level, CFmDbEventLog::data_type event_map) {
char * output = (char*) malloc(2048);
char * msg = formattedEvent(event_map, output, 2048);
fmLogMsg(level,msg);
free(output);
}
void fmLogAddEventLog(SFmAlarmDataT * data, bool is_event_suppressed){
pthread_mutex_lock(&mutex);
CFmDbEventLog event;
CFmDbEventLog::data_type event_map;
event.create_data(data);
event.export_data(event_map);
fmLogEVT(fmLogLevelInfo | LOG_LOCAL5, event_map);
pthread_mutex_unlock(&mutex);
}
// Converts a string (s) to be json safe. Special characters are escaped and written to buffer.
static char * escape_json(const char * s, char * buffer, const int bufLen) {
int sLen = -1;
int bufLeft = bufLen;
int s_i = 0;
int buf_i = 0;
int ch;
char tmp_buf[16];
char * escapedChrs = NULL;
int escapedChrsLen = -1;
if (s==NULL || buffer==NULL || bufLen<1) {
return buffer;
}
sLen = strlen(s);
buffer[0] = 0;
if (s == 0) {
return buffer;
}
while (s_i < sLen && bufLeft > 0) {
ch = s[s_i];
switch (ch) {
case '\"':
escapedChrs = (char *) "\\\"";
break;
case '\\':
escapedChrs = (char *) "\\\\";
break;
case '\b':
escapedChrs = (char *) "\\b";
break;
case '\f':
escapedChrs = (char *) "\\f";
break;
case '\n':
escapedChrs = (char *) "\\n";
break;
case '\r':
escapedChrs = (char *) "\\r";
break;
case '\t':
escapedChrs = (char *) "\\t";
break;
default:
if (ch < 0) {
ch = 0xFFFD; /* replacement character */
}
if (ch > 0xFFFF) {
/* beyond BMP (Basic Multilingual Plane); need a surrogate pair
* for reference, see: https://en.wikipedia.org/wiki/Plane_%28Unicode%29
*/
snprintf(tmp_buf, sizeof(tmp_buf), "\\u%04X\\u%04X",
0xD800 + ((ch - 0x10000) >> 10),
0xDC00 + ((ch - 0x10000) & 0x3FF));
} else if (ch < 0x20 || ch >= 0x7F) {
snprintf(tmp_buf, sizeof(tmp_buf), "\\u%04X", ch);
} else {
tmp_buf[0] = ch;
tmp_buf[1] = 0;
}
escapedChrs = tmp_buf;
}
escapedChrsLen = strlen(escapedChrs);
if (bufLeft <= escapedChrsLen) {
break;
}
strncpy(&buffer[buf_i], escapedChrs, bufLeft );
bufLeft -= escapedChrsLen;
buf_i += escapedChrsLen;
s_i++;
}
return buffer;
}