forked from sonic-net/sonic-buildimage
-
Notifications
You must be signed in to change notification settings - Fork 0
Add rsyslog plugin and tests #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
zbud-msft
merged 8 commits into
renukamanavalan:syslog_telemetry_shared
from
zbud-msft:zbud-msft
Jun 27, 2022
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
999a175
Add rsyslog plugin and tests
3082cf8
Add syslog if init fails
ee28577
Fix onInit logic
7cb88d7
Add makefile and resolve PR comments
b92bb29
Remove redundant headers, etc
4468e11
Add logic for empty regex expressions
0eec661
Remove redundant syslog messages
5916a5a
Resolve PR comments
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| RM := rm -rf | ||
| 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 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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(); | ||
renukamanavalan marked this conversation as resolved.
Show resolved
Hide resolved
zbud-msft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return SUCCESS_CODE; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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, ¶mDict); | ||
| 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; | ||
zbud-msft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| [[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; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 ' ' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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