Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
47 changes: 47 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <iostream>
#include <unistd.h>
#include "rsyslog_plugin.h"

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 regex_path;
string module_name;
int option_val;

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

if(regex_path.empty() || module_name.empty()) { // Missing required rc path
cerr << "Error: Missing regex_path and module_name." << endl;
return 1;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1

Since there are multiple exit reason, let's define multiple return code, and user macro name.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

}

RsyslogPlugin* plugin = new RsyslogPlugin(module_name, regex_path);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

new

memory leak. Suggest use smart pointer

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I believe LGTM could catch this kind of critical bug. Suggest you raise a draft PR to public repo, so you will have all PR checkers result, like build/lgtm/coverage.

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.

new

memory leak. Suggest use smart pointer

There is no mem leak here, as process exits at that point. Said that, valgrind will not be happy and it is always a good idea to make clean exit.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Changed to smart pointer.

if(!plugin->onInit()) {
SWSS_LOG_ERROR("Rsyslog plugin was not able to be initialized.\n");
return 1;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Mixing tabs and spaces, prefer 4-space each indentation level.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

}

plugin->run();
return 0;
}
86 changes: 86 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/rsyslog_plugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <ios>
#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 param_dict;
if(!m_parser->parseMessage(msg, tag, param_dict)) {
SWSS_LOG_DEBUG("%s was not able to be parsed into a structured event\n", msg.c_str());
return false;
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 same. Please check all the files.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

} else {
int return_code = event_publish(m_event_handle, tag, &param_dict);
if (return_code != 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 regex_file;
regex_file.open(m_regex_path, ios::in);
if (!regex_file) {
SWSS_LOG_ERROR("No such path exists: %s for source %s\n", m_regex_path.c_str(), m_module_name.c_str());
return false;
}
try {
regex_file >> m_parser->m_regex_list;
} catch (exception& exception) {
SWSS_LOG_ERROR("Invalid JSON file: %s, throws exception: %s\n", m_regex_path.c_str(), exception.what());
return false;
}

string regex_string;
regex expression;

for(long unsigned int i = 0; i < m_parser->m_regex_list.size(); i++) {
try {
regex_string = m_parser->m_regex_list[i]["regex"];
string tag = m_parser->m_regex_list[i]["tag"];
vector<string> params = m_parser->m_regex_list[i]["params"];
regex expr(regex_string);
expression = expr;
} catch (exception& exception) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

exception

Do not catch general exception in normal use cases. It will hide bugs. Use more specific types.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

SWSS_LOG_ERROR("Invalid regex, throws exception: %s\n", exception.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;
}
regex_file.close();
return true;
}

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

bool RsyslogPlugin::onInit() {
m_event_handle = events_init_publisher(m_module_name);
bool return_code = createRegexList();
return (m_event_handle != NULL && return_code);
}

RsyslogPlugin::RsyslogPlugin(string module_name, string regex_path) {
m_parser = new SyslogParser({}, json::array());
m_module_name = module_name;
m_regex_path = regex_path;
}
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 "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:
bool onInit();
bool onMessage(string msg);
void run();
RsyslogPlugin(string module_name, string regex_path);
private:
SyslogParser* m_parser;
Copy link
Copy Markdown
Owner

@renukamanavalan renukamanavalan Jun 19, 2022

Choose a reason for hiding this comment

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

In line with Qi's comments, you may make this shared-ptr too, so it gets deleted when this object gets deleted.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Using smart pointer now

event_handle_t m_event_handle;
string m_regex_path;
string m_module_name;

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 ' '
33 changes: 33 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/syslog_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#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& event_tag, event_params_t& param_map) {
for(long unsigned int i = 0; i < m_regex_list.size(); i++) {
smatch match_results;
vector<string> params = m_regex_list[i]["params"];
if(!regex_search(message, match_results, m_expressions[i]) || params.size() != match_results.size() - 1) {
continue;
}
// found matching regex
event_tag = m_regex_list[i]["tag"];
transform(params.begin(), params.end(), match_results.begin() + 1, inserter(param_map, param_map.end()), [](string a, string b) {
return make_pair(a,b);
});
return true;
}
return false;
}

SyslogParser::SyslogParser(vector<regex> expressions, json regex_list) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

vector

copy ctor of vector and json are expensive. Use const reference?

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.

The args are redundant. You may drop them, as you are constructing with empty objects and manipulating the objects directly.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Removed args

m_expressions = expressions;
m_regex_list = regex_list;
}
28 changes: 28 additions & 0 deletions src/sonic-eventd/rsyslog_plugin/syslog_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#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_regex_list = json::array();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

m_regex_list

Naming convention: m_regexList

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.


SyslogParser(vector<regex> expressions, json regex_list);
bool parseMessage(string message, string& tag, event_params_t& param_dict);
};

#endif
Loading