You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
6.7 KiB
254 lines
6.7 KiB
// Module: Log4CPLUS
|
|
// File: log4judpappender.cxx
|
|
// Created: 7/2012
|
|
// Author: Siva Chandran P
|
|
//
|
|
//
|
|
// Copyright 2012-2013 Siva Chandran P
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <log4cplus/log4judpappender.h>
|
|
#include <log4cplus/layout.h>
|
|
#include <log4cplus/streams.h>
|
|
#include <log4cplus/helpers/loglog.h>
|
|
#include <log4cplus/helpers/property.h>
|
|
#include <log4cplus/spi/loggingevent.h>
|
|
#include <log4cplus/internal/internal.h>
|
|
#include <log4cplus/thread/syncprims-pub-impl.h>
|
|
#include <iomanip>
|
|
#include <cstring>
|
|
#if defined (UNICODE)
|
|
#include <cwctype>
|
|
#else
|
|
#include <cctype>
|
|
#endif
|
|
|
|
|
|
namespace log4cplus
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
|
|
static inline bool
|
|
is_control (tchar ch)
|
|
{
|
|
#if defined (UNICODE)
|
|
return !! std::iswcntrl (std::char_traits<tchar>::to_int_type (ch));
|
|
#else
|
|
return !! std::iscntrl (std::char_traits<tchar>::to_int_type (ch));
|
|
#endif
|
|
}
|
|
|
|
|
|
//! Outputs str with reserved XML characters escaped.
|
|
static
|
|
void
|
|
output_xml_escaped (tostream & os, tstring const & str)
|
|
{
|
|
for (tstring::const_iterator it = str.begin (); it != str.end (); ++it)
|
|
{
|
|
tchar const & ch = *it;
|
|
switch (ch)
|
|
{
|
|
case LOG4CPLUS_TEXT ('<'):
|
|
os << LOG4CPLUS_TEXT ("<");
|
|
break;
|
|
|
|
case LOG4CPLUS_TEXT ('>'):
|
|
os << LOG4CPLUS_TEXT (">");
|
|
break;
|
|
|
|
case LOG4CPLUS_TEXT ('&'):
|
|
os << LOG4CPLUS_TEXT ("&");
|
|
break;
|
|
|
|
case LOG4CPLUS_TEXT ('\''):
|
|
os << LOG4CPLUS_TEXT ("'");
|
|
break;
|
|
|
|
case LOG4CPLUS_TEXT ('"'):
|
|
os << LOG4CPLUS_TEXT (""");
|
|
break;
|
|
|
|
default:
|
|
if (is_control (ch))
|
|
{
|
|
tchar const prev_fill = os.fill ();
|
|
std::ios_base::fmtflags const prev_flags = os.flags ();
|
|
os.flags (std::ios_base::hex | std::ios_base::right);
|
|
os.fill (LOG4CPLUS_TEXT ('0'));
|
|
|
|
os << std::setw (0) << LOG4CPLUS_TEXT ("&#x")
|
|
<< std::setw (2) << std::char_traits<tchar>::to_int_type (ch)
|
|
<< std::setw (0) << LOG4CPLUS_TEXT (";");
|
|
|
|
os.fill (prev_fill);
|
|
os.flags (prev_flags);
|
|
}
|
|
else
|
|
os.put (ch);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//! Helper manipulator like class for escaped XML output.
|
|
struct outputXMLEscaped
|
|
{
|
|
outputXMLEscaped (tstring const & s)
|
|
: str (s)
|
|
{ }
|
|
|
|
tstring const & str;
|
|
};
|
|
|
|
|
|
//! Overload stream insertion for outputXMLEscaped.
|
|
static
|
|
tostream &
|
|
operator << (tostream & os, outputXMLEscaped const & x)
|
|
{
|
|
output_xml_escaped (os, x.str);
|
|
return os;
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Log4jUdpAppender ctors and dtor
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
Log4jUdpAppender::Log4jUdpAppender(const tstring& host_, int port_)
|
|
: host(host_)
|
|
, port(port_)
|
|
{
|
|
layout.reset (new PatternLayout (LOG4CPLUS_TEXT ("%m")));
|
|
openSocket();
|
|
}
|
|
|
|
|
|
|
|
Log4jUdpAppender::Log4jUdpAppender(const helpers::Properties & properties)
|
|
: Appender(properties)
|
|
, port(5000)
|
|
{
|
|
host = properties.getProperty( LOG4CPLUS_TEXT("host"),
|
|
LOG4CPLUS_TEXT ("localhost") );
|
|
properties.getInt (port, LOG4CPLUS_TEXT ("port"));
|
|
|
|
openSocket();
|
|
}
|
|
|
|
|
|
|
|
Log4jUdpAppender::~Log4jUdpAppender()
|
|
{
|
|
destructorImpl();
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Log4jUdpAppender public methods
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
Log4jUdpAppender::close()
|
|
{
|
|
helpers::getLogLog().debug(
|
|
LOG4CPLUS_TEXT("Entering Log4jUdpAppender::close()..."));
|
|
|
|
socket.close();
|
|
closed = true;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Log4jUdpAppender protected methods
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
Log4jUdpAppender::openSocket()
|
|
{
|
|
if(!socket.isOpen()) {
|
|
socket = helpers::Socket(host, port, true);
|
|
}
|
|
}
|
|
|
|
void
|
|
Log4jUdpAppender::append(const spi::InternalLoggingEvent& event)
|
|
{
|
|
if(!socket.isOpen()) {
|
|
openSocket();
|
|
if(!socket.isOpen()) {
|
|
helpers::getLogLog().error(
|
|
LOG4CPLUS_TEXT("Log4jUdpAppender::append()- Cannot connect to server"));
|
|
return;
|
|
}
|
|
}
|
|
|
|
tstring & str = formatEvent (event);
|
|
|
|
internal::appender_sratch_pad & appender_sp
|
|
= internal::get_appender_sp ();
|
|
tostringstream & buffer = appender_sp.oss;
|
|
detail::clear_tostringstream (buffer);
|
|
|
|
buffer << LOG4CPLUS_TEXT("<log4j:event logger=\"")
|
|
<< outputXMLEscaped (event.getLoggerName())
|
|
<< LOG4CPLUS_TEXT("\" level=\"")
|
|
// TODO: Some escaping of special characters is needed here.
|
|
<< outputXMLEscaped (getLogLevelManager().toString(event.getLogLevel()))
|
|
<< LOG4CPLUS_TEXT("\" timestamp=\"")
|
|
<< event.getTimestamp().getFormattedTime(LOG4CPLUS_TEXT("%s%q"))
|
|
<< LOG4CPLUS_TEXT("\" thread=\"") << event.getThread()
|
|
<< LOG4CPLUS_TEXT("\">")
|
|
|
|
<< LOG4CPLUS_TEXT("<log4j:message>")
|
|
// TODO: Some escaping of special characters is needed here.
|
|
<< outputXMLEscaped (str)
|
|
<< LOG4CPLUS_TEXT("</log4j:message>")
|
|
|
|
<< LOG4CPLUS_TEXT("<log4j:NDC>")
|
|
// TODO: Some escaping of special characters is needed here.
|
|
<< outputXMLEscaped (event.getNDC())
|
|
<< LOG4CPLUS_TEXT("</log4j:NDC>")
|
|
|
|
<< LOG4CPLUS_TEXT("<log4j:locationInfo class=\"\" file=\"")
|
|
// TODO: Some escaping of special characters is needed here.
|
|
<< outputXMLEscaped (event.getFile())
|
|
<< LOG4CPLUS_TEXT("\" method=\"")
|
|
<< outputXMLEscaped (event.getFunction())
|
|
<< LOG4CPLUS_TEXT("\" line=\"")
|
|
<< event.getLine()
|
|
<< LOG4CPLUS_TEXT("\"/>")
|
|
<< LOG4CPLUS_TEXT("</log4j:event>");
|
|
|
|
LOG4CPLUS_TSTRING_TO_STRING (buffer.str ()).swap (appender_sp.chstr);
|
|
|
|
bool ret = socket.write(appender_sp.chstr);
|
|
if (!ret)
|
|
{
|
|
helpers::getLogLog().error(
|
|
LOG4CPLUS_TEXT(
|
|
"Log4jUdpAppender::append()- Cannot write to server"));
|
|
}
|
|
}
|
|
|
|
} // namespace log4cplus
|