Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions src/sonic-eventd/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
RM := rm -rf
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other components in this repo is using Debian package build infra, not plain Makefile. Could you adapt?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is using debian package -- pretty similar to dhcp-relay

EVENTD_TARGET := eventd
EVENTD_TEST := tests/tests
EVENTD_TOOL := tools/events_tool
RSYSLOG-PLUGIN_TARGET := rsyslog_plugin
RSYSLOG-PLUGIN_TEST: rsyslog_plugin_tests/tests
CP := cp
MKDIR := mkdir
CC := g++
MV := mv
LIBS := -levent -lhiredis -lswsscommon -lpthread -lboost_thread -lboost_system -lzmq -lboost_serialization -luuid
TEST_LIBS := -L/usr/src/gtest -lgtest -lgtest_main -lgmock -lgmock_main

CFLAGS += -Wall -std=c++17 -fPIE -I$(PWD)/../sonic-swss-common/common
PWD := $(shell pwd)

ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS) $(OBJS)
endif
endif

-include src/subdir.mk
-include tests/subdir.mk
-include tools/subdir.mk
-include rsyslog_plugin/subdir.mk

all: sonic-eventd eventd-tests eventd-tool rsyslog-plugin rsyslog-plugin-tests

sonic-eventd: $(OBJS)
@echo 'Building target: $@'
@echo 'Invoking: G++ Linker'
$(CC) $(LDFLAGS) -o $(EVENTD_TARGET) $(OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '

eventd-tool: $(TOOL_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: G++ Linker'
$(CC) $(LDFLAGS) -o $(EVENTD_TOOL) $(TOOL_OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '

rsyslog-plugin: $(RSYSLOG-PLUGIN_OBJS)
@echo 'Buidling Target: $@'
@echo 'Invoking: G++ Linker'
$(CC) $(LDFLAGS) -o $(RSYSLOG-PLUGIN_TARGET) $(RSYSLOG-PLUGIN_OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '

eventd-tests: $(TEST_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: G++ Linker'
$(CC) $(LDFLAGS) -o $(EVENTD_TEST) $(TEST_OBJS) $(LIBS) $(TEST_LIBS)
@echo 'Finished building target: $@'
$(EVENTD_TEST)
@echo 'Finished running tests'
@echo ' '

rsyslog-plugin-tests: $(RSYSLOG-PLUGIN-TEST_OBJS)
@echo 'BUILDING target: $@'
@echo 'Invoking G++ Linker'
$(CC) $(LDFLAGS) -o $(RSYSLOG-PLUGIN_TEST) $(RSYSLOG-PLUGIN-TEST_OBJS) $(LIBS) $(TEST_LIBS)
@echo 'Finished building target: $@'
$(RSYSLOG-PLUGIN_TEST)
@echo 'Finished running tests'
@echo ' '

install:
$(MKDIR) -p $(DESTDIR)/usr/sbin
$(MV) $(EVENTD_TARGET) $(DESTDIR)/usr/sbin
$(MV) $(EVENTD_TOOL) $(DESTDIR)/usr/sbin
$(MV) $(RSYSLOG-PLUGIN_TARGET) $(DESTDIR)/usr/sbin

deinstall:
$(RM) $(DESTDIR)/usr/sbin/$(EVENTD_TARGET)
$(RM) $(DESTDIR)/usr/sbin/$(RSYSLOG-PLUGIN_TARGET)
$(RM) -rf $(DESTDIR)/usr/sbin

clean:
-@echo ' '

.PHONY: all clean dependents
57 changes: 57 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <iostream>
#include <memory>
#include <unistd.h>
#include "rsyslog_plugin.h"

#define SUCCESS_CODE 0
#define INVALID_REGEX_ERROR_CODE 1
#define EVENT_INIT_PUBLISH_ERROR_CODE 2
#define MISSING_ARGS_ERROR_CODE 3

void showUsage() {
cout << "Usage for rsyslog_plugin: \n" << "options\n"
<< "\t-r,required,type=string\t\tPath to regex file\n"
<< "\t-m,required,type=string\t\tYANG module name of source generating syslog message\n"
<< "\t-h \t\tHelp"
<< endl;
}

int main(int argc, char** argv) {
string regexPath;
string moduleName;
int optionVal;

while((optionVal = getopt(argc, argv, "r:m:h")) != -1) {
switch(optionVal) {
case 'r':
regexPath = optarg;
break;
case 'm':
moduleName = optarg;
break;
case 'h':
case '?':
default:
showUsage();
return 1;
}
}

if(regexPath.empty() || moduleName.empty()) { // Missing required rc path
cerr << "Error: Missing regexPath and moduleName." << endl;
return MISSING_ARGS_ERROR_CODE;
}

unique_ptr<RsyslogPlugin> plugin(new RsyslogPlugin(moduleName, regexPath));
int returnCode = plugin->onInit();
if(returnCode == INVALID_REGEX_ERROR_CODE) {
SWSS_LOG_ERROR("Rsyslog plugin was not able to be initialized due to invalid regex file provided.\n");
return returnCode;
} else if(returnCode == EVENT_INIT_PUBLISH_ERROR_CODE) {
SWSS_LOG_ERROR("Rsyslog plugin was not able to be initialized due to event_init_publish call failing.\n");
return returnCode;
}

plugin->run();
return SUCCESS_CODE;
}
93 changes: 93 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/rsyslog_plugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include <iostream>
#include <vector>
#include <fstream>
#include <regex>
#include "rsyslog_plugin.h"
#include "common/json.hpp"

using json = nlohmann::json;

bool RsyslogPlugin::onMessage(string msg) {
string tag;
event_params_t paramDict;
if(!m_parser->parseMessage(msg, tag, paramDict)) {
SWSS_LOG_DEBUG("%s was not able to be parsed into a structured event\n", msg.c_str());
return false;
} else {
int returnCode = event_publish(m_eventHandle, tag, &paramDict);
if (returnCode != 0) {
SWSS_LOG_ERROR("rsyslog_plugin was not able to publish event for %s. last thrown event error: %d\n", tag.c_str(), event_last_error());
return false;
}
return true;
}
}

bool RsyslogPlugin::createRegexList() {
fstream regexFile;
regexFile.open(m_regexPath, ios::in);
if (!regexFile) {
SWSS_LOG_ERROR("No such path exists: %s for source %s\n", m_regexPath.c_str(), m_moduleName.c_str());
return false;
}
try {
regexFile >> m_parser->m_regexList;
} catch (invalid_argument& iaException) {
SWSS_LOG_ERROR("Invalid JSON file: %s, throws exception: %s\n", m_regexPath.c_str(), iaException.what());
return false;
}

string regexString;
regex expression;

for(long unsigned int i = 0; i < m_parser->m_regexList.size(); i++) {
try {
regexString = m_parser->m_regexList[i]["regex"];
string tag = m_parser->m_regexList[i]["tag"];
vector<string> params = m_parser->m_regexList[i]["params"];
regex expr(regexString);
expression = expr;
} catch (domain_error& deException) {
SWSS_LOG_ERROR("Missing required key, throws exception: %s\n", deException.what());
return false;
} catch (regex_error& reException) {
SWSS_LOG_ERROR("Invalid regex, throws exception: %s\n", reException.what());
return false;
}
m_parser->m_expressions.push_back(expression);
}
if(m_parser->m_expressions.empty()) {
SWSS_LOG_ERROR("Empty list of regex expressions.\n");
return false;
}
regexFile.close();
return true;
}

[[noreturn]] void RsyslogPlugin::run() {
while(true) {
string line;
getline(cin, line);
if(line.empty()) {
continue;
}
onMessage(line);
}
}

int RsyslogPlugin::onInit() {
m_eventHandle = events_init_publisher(m_moduleName);
bool success = createRegexList();
if(!success) {
return 1; // invalid regex error code
} else if(m_eventHandle == NULL) {
return 2; // event init publish error code
}
return 0;
}

RsyslogPlugin::RsyslogPlugin(string moduleName, string regexPath) {
m_parser = unique_ptr<SyslogParser>(new SyslogParser());
m_moduleName = moduleName;
m_regexPath = regexPath;
}
34 changes: 34 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/rsyslog_plugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef RSYSLOG_PLUGIN_H
#define RSYSLOG_PLUGIN_H

#include <string>
#include <memory>
#include "syslog_parser.h"
#include "common/events.h"
#include "common/logger.h"

using namespace std;
using namespace swss;

/**
* Rsyslog Plugin will utilize an instance of a syslog parser to read syslog messages from rsyslog.d and will continuously read from stdin
* A plugin instance is created for each container/host.
*
*/

class RsyslogPlugin {
public:
int onInit();
bool onMessage(string msg);
void run();
RsyslogPlugin(string moduleName, string regexPath);
private:
unique_ptr<SyslogParser> m_parser;
event_handle_t m_eventHandle;
string m_regexPath;
string m_moduleName;
bool createRegexList();
};

#endif

13 changes: 13 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/subdir.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CC := g++

RSYSLOG-PLUGIN_TEST_OBJS += ./rsyslog_plugin/rsyslog_plugin.o ./rsyslog_plugin/syslog_parser.o
RSYSLOG-PLUGIN_OBJS += ./rsyslog_plugin/rsyslog_plugin.o ./rsyslog_plugin/syslog_parser.o ./rsyslog_plugin/main.o

C_DEPS += ./rsyslog_plugin/rsyslog_plugin.d ./rsyslog_plugin/syslog_parser.d ./rsyslog_plugin/main.d

rsyslog_plugin/%.o: rsyslog_plugin/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: GCC C++ Compiler'
$(CC) -D__FILENAME__="$(subst rsyslog_plugin/,,$<)" $(CFLAGS) -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$(@)" "$<"
@echo 'Finished building: $<
'@echo ' '
28 changes: 28 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/syslog_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <iostream>
#include "syslog_parser.h"
#include "common/logger.h"

/**
* Parses syslog message and returns structured event
*
* @param nessage us syslog message being fed in by rsyslog.d
* @return return structured event json for publishing
*
*/

bool SyslogParser::parseMessage(string message, string& eventTag, event_params_t& paramMap) {
for(long unsigned int i = 0; i < m_regexList.size(); i++) {
smatch matchResults;
vector<string> params = m_regexList[i]["params"];
if(!regex_search(message, matchResults, m_expressions[i]) || params.size() != matchResults.size() - 1) {
continue;
}
// found matching regex
eventTag = m_regexList[i]["tag"];
transform(params.begin(), params.end(), matchResults.begin() + 1, inserter(paramMap, paramMap.end()), [](string a, string b) {
return make_pair(a,b);
});
return true;
}
return false;
}
26 changes: 26 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/syslog_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef SYSLOG_PARSER_H
#define SYSLOG_PARSER_H

#include <vector>
#include <string>
#include <regex>
#include "common/json.hpp"
#include "common/events.h"

using namespace std;
using json = nlohmann::json;

/**
* Syslog Parser is responsible for parsing log messages fed by rsyslog.d and returns
* matched result to rsyslog_plugin to use with events publish API
*
*/

class SyslogParser {
public:
vector<regex> m_expressions;
json m_regexList = json::array();
bool parseMessage(string message, string& tag, event_params_t& paramDict);
};

#endif
Loading