f8716aa344
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>
177 lines
5.4 KiB
C++
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;
|
|
}
|