RemoteSyslogChannel should allow the RFC 5424 STRUCTURED-DATA field to be set #2173

This commit is contained in:
Günter Obiltschnig 2018-03-07 06:51:39 +01:00
parent 826dc92fda
commit 69588abd71
6 changed files with 120 additions and 0 deletions

View File

@ -126,6 +126,7 @@ public:
static const std::string PROP_FORMAT;
static const std::string PROP_LOGHOST;
static const std::string PROP_HOST;
static const std::string STRUCTURED_DATA;
protected:
~RemoteSyslogChannel();

View File

@ -98,6 +98,7 @@ public:
static const std::string LOG_PROP_APP;
static const std::string LOG_PROP_HOST;
static const std::string LOG_PROP_STRUCTURED_DATA;
protected:
~RemoteSyslogListener();

View File

@ -34,6 +34,7 @@ const std::string RemoteSyslogChannel::PROP_FACILITY("facility");
const std::string RemoteSyslogChannel::PROP_FORMAT("format");
const std::string RemoteSyslogChannel::PROP_LOGHOST("loghost");
const std::string RemoteSyslogChannel::PROP_HOST("host");
const std::string RemoteSyslogChannel::STRUCTURED_DATA("structured-data");
RemoteSyslogChannel::RemoteSyslogChannel():
@ -137,6 +138,15 @@ void RemoteSyslogChannel::log(const Message& msg)
Poco::NumberFormatter::append(m, msg.getPid());
m += ' ';
m += msg.getSource();
m += ' ';
if (msg.has(STRUCTURED_DATA))
{
m += msg.get(STRUCTURED_DATA);
}
else
{
m += "-";
}
}
m += ' ';
m += msg.getText();

View File

@ -178,6 +178,12 @@ private:
/// Parses until it encounters the next space char, returns the string from pos, excluding space
/// pos will point past the space char
static std::string parseStructuredData(const std::string& line, std::size_t& pos);
/// Parses the structured data field.
static std::string parseStructuredDataToken(const std::string& line, std::size_t& pos);
/// Parses a token from the structured data field.
private:
Poco::NotificationQueue& _queue;
bool _stopped;
@ -295,6 +301,7 @@ void SyslogParser::parseNew(const std::string& line, RemoteSyslogChannel::Severi
std::string appName(parseUntilSpace(line, pos));
std::string procId(parseUntilSpace(line, pos));
std::string msgId(parseUntilSpace(line, pos));
std::string sd(parseStructuredData(line, pos));
std::string messageText(line.substr(pos));
pos = line.size();
Poco::DateTime date;
@ -303,6 +310,7 @@ void SyslogParser::parseNew(const std::string& line, RemoteSyslogChannel::Severi
Poco::Message logEntry(msgId, messageText, prio);
logEntry[RemoteSyslogListener::LOG_PROP_HOST] = hostName;
logEntry[RemoteSyslogListener::LOG_PROP_APP] = appName;
logEntry[RemoteSyslogListener::LOG_PROP_STRUCTURED_DATA] = sd;
if (hasDate)
logEntry.setTime(date.timestamp());
@ -393,6 +401,67 @@ std::string SyslogParser::parseUntilSpace(const std::string& line, std::size_t&
}
std::string SyslogParser::parseStructuredData(const std::string& line, std::size_t& pos)
{
std::string sd;
if (pos < line.size())
{
if (line[pos] == '-')
{
++pos;
}
else if (line[pos] == '[')
{
std::string tok = parseStructuredDataToken(line, pos);
while (tok == "[")
{
sd += tok;
tok = parseStructuredDataToken(line, pos);
while (tok != "]" && !tok.empty())
{
sd += tok;
tok = parseStructuredDataToken(line, pos);
}
sd += tok;
if (pos < line.size() && line[pos] == '[') tok = parseStructuredDataToken(line, pos);
}
}
if (pos < line.size() && Poco::Ascii::isSpace(line[pos])) ++pos;
}
return sd;
}
std::string SyslogParser::parseStructuredDataToken(const std::string& line, std::size_t& pos)
{
std::string tok;
if (pos < line.size())
{
if (Poco::Ascii::isSpace(line[pos]) || line[pos] == '=' || line[pos] == '[' || line[pos] == ']')
{
tok += line[pos++];
}
else if (line[pos] == '"')
{
tok += line[pos++];
while (pos < line.size() && line[pos] != '"')
{
tok += line[pos++];
}
tok += '"';
if (pos < line.size()) pos++;
}
else
{
while (pos < line.size() && !Poco::Ascii::isSpace(line[pos]) && line[pos] != '=')
{
tok += line[pos++];
}
}
}
return tok;
}
Poco::Message::Priority SyslogParser::convert(RemoteSyslogChannel::Severity severity)
{
switch (severity)
@ -428,6 +497,7 @@ const std::string RemoteSyslogListener::PROP_THREADS("threads");
const std::string RemoteSyslogListener::LOG_PROP_APP("app");
const std::string RemoteSyslogListener::LOG_PROP_HOST("host");
const std::string RemoteSyslogListener::LOG_PROP_STRUCTURED_DATA("structured-data");
RemoteSyslogListener::RemoteSyslogListener():

View File

@ -211,6 +211,42 @@ void SyslogTest::testOldBSD()
}
void SyslogTest::testStructuredData()
{
Poco::AutoPtr<RemoteSyslogChannel> channel = new RemoteSyslogChannel();
channel->setProperty("loghost", "127.0.0.1:51400");
channel->open();
Poco::AutoPtr<RemoteSyslogListener> listener = new RemoteSyslogListener(51400);
listener->open();
CachingChannel cl;
listener->addChannel(&cl);
assert(cl.getCurrentSize() == 0);
Poco::Message msg1("asource", "amessage", Poco::Message::PRIO_CRITICAL);
msg1.set("structured-data", "[exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"]");
channel->log(msg1);
Poco::Message msg2("asource", "amessage", Poco::Message::PRIO_CRITICAL);
msg2.set("structured-data", "[exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"][examplePriority@32473 class=\"high\"]");
channel->log(msg2);
Poco::Thread::sleep(1000);
listener->close();
channel->close();
assert(cl.getCurrentSize() == 2);
std::vector<Poco::Message> msgs;
cl.getMessages(msgs, 0, 10);
assert(msgs.size() == 2);
assert(msgs[0].getSource() == "asource");
assert(msgs[0].getText() == "amessage");
assert(msgs[0].getPriority() == Poco::Message::PRIO_CRITICAL);
assert(msgs[0].get("structured-data") == "[exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"][examplePriority@32473 class=\"high\"]");
assert(msgs[1].getSource() == "asource");
assert(msgs[1].getText() == "amessage");
assert(msgs[1].getPriority() == Poco::Message::PRIO_CRITICAL);
assert(msgs[1].get("structured-data") == "[exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"]");
}
void SyslogTest::setUp()
{
}
@ -228,6 +264,7 @@ CppUnit::Test* SyslogTest::suite()
CppUnit_addTest(pSuite, SyslogTest, testListener);
CppUnit_addTest(pSuite, SyslogTest, testChannelOpenClose);
CppUnit_addTest(pSuite, SyslogTest, testOldBSD);
CppUnit_addTest(pSuite, SyslogTest, testStructuredData);
return pSuite;
}

View File

@ -27,6 +27,7 @@ public:
void testListener();
void testChannelOpenClose();
void testOldBSD();
void testStructuredData();
void setUp();
void tearDown();