// // Copyright (c) 2014 Wind River Systems, Inc. // // SPDX-License-Identifier: Apache-2.0 // #include #include #include #include "fmLog.h" #include "fmDbAlarm.h" #include "fmDbEventLog.h" #include #include 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)); } has_inited=true; } void fmLogMsg(int level, const char *data,...){ va_list ap; va_start(ap, data); vsyslog(level,data,ap); va_end(ap); } bool fmLogFileInit(){ fmLoggingInit(); return true; } // 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\" }", "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; }