2008年10月30日木曜日

boost::asio syslog

以前cppllにポストしたものですが、boost-1.36.0用に焼き直したものを貼っときます。

// syslog daemon sample
#include <boost/asio.hpp>
#include <boost/bind.hpp>

class syslog_daemon {
public:
syslog_daemon(
boost::asio::io_service& io_service,
short port = 514
) :
io_service_(io_service),
socket_(
io_service,
boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port)
)
{
invoke_recieve();
}

void handle_receive_from(
const boost::system::error_code& error,
size_t bytes_recvd
) {
if( error ) {
} else {
if( bytes_recvd > 0 ) {
std::string log;
log.assign( &data_[0], &data_[bytes_recvd] );
std::cout << log << std::endl;
// do logging
}
invoke_recieve();
}
}

private:
void invoke_recieve() {
socket_.async_receive_from(
boost::asio::buffer( data_, buffer_length ),
sender_endpoint_,
boost::bind(
&syslog_daemon::handle_receive_from,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}

private:
enum { buffer_length = 4096, };
char data_[ buffer_length ];
boost::asio::io_service& io_service_;
boost::asio::ip::udp::socket socket_;
boost::asio::ip::udp::endpoint sender_endpoint_;
};

int main() {
try {
boost::asio::io_service io_service;
syslog_daemon sd( io_service );
io_service.run();
} catch( std::exception& e ) {
std::cout << e.what() << std::endl;
}
return 0;
}



// syslog send sample
#include <string>
#include <boost/asio.hpp>
#include <boost/date_time/date_facet.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

//! syslog facility code
enum syslog_facility {
kernel_messages = 0,
user_level_messages = 1,
mail_system_messages = 2,
system_daemons = 3,
security_authorization_messages = 4,
messages_generated_internally_by_syslogd = 5,
line_printer_subsystem = 6,
network_news_subsystem = 7,
subsystem = 8,
clock_daemon = 9,
security_authorization_messages2 = 10,
ftp_daemon = 11,
ntp_daemon = 12,
log_audit = 13,
log_alert = 14,
clock_daemon2 = 15,
local_use0 = 16,
local_use1 = 17,
local_use2 = 18,
local_use3 = 19,
local_use4 = 20,
local_use5 = 21,
local_use6 = 22,
local_use7 = 23,
};

//! syslog severity code
enum syslog_severity {
emergency = 0, // system is unusable
alert = 1, // action must be taken immediately
critical = 2, // critical conditions
error = 3, // error conditions
warning = 4, // warning conditions
notice = 5, // normal but significant condition
information = 6, // informational messages
debug = 7, // debug-level messages
};

//! get syslog PRI part
/*!
@retval syslog PRI part string.
*/
std::string get_pri_part(
syslog_facility facility, //!< [in] facility code
syslog_severity severity //!< [in] severity code
) {
std::ostringstream oss;
oss << "<" << (facility * 8 + severity) << ">";
return oss.str();
}

//! get syslog HEAD part
/*!
@retval syslog HEAD part
*/
std::string get_head_part(
const boost::posix_time::ptime& ptime,
const boost::asio::ip::address_v4& address
) {
typedef boost::date_time::time_facet<boost::posix_time::ptime, char> ldt_facet;
ldt_facet* facet = new ldt_facet("%b %d %H:%M:%S");
std::ostringstream oss;
oss.imbue( std::locale( std::locale::classic(), facet ) );
oss << ptime << " " << address << " ";
return oss.str();
}

//! get syslog MSG part
/*!
@attention
@retval syslog MSG part
*/
std::string get_msg_part(
const std::string& tag, //!< [in] tag
const std::string& msg //!< [in] message
) {
BOOST_ASSERT( tag.size() <= 32 );
std::ostringstream oss;
oss << tag << ":" << msg;
return oss.str();
}

class syslog_transfer {
public:
syslog_transfer(
boost::asio::io_service& io_service ) :
io_service_(io_service),
resolver_(io_service),
socket_(
io_service,
boost::asio::ip::udp::endpoint( boost::asio::ip::udp::v4(), 0)
)
{
}

void connect( const std::string& host_name, const std::string& port ) {
boost::asio::ip::udp::resolver::query query( boost::asio::ip::udp::v4(), host_name.c_str(), port.c_str() );
iter_ = resolver_.resolve( query );
}

void transfer( const std::string& log ) {
boost::asio::ip::udp::resolver::iterator iter = iter_;
socket_.send_to( boost::asio::buffer( log, log.size() ), *iter );
}

private:
boost::asio::io_service& io_service_;
boost::asio::ip::udp::resolver resolver_;
boost::asio::ip::udp::resolver::iterator iter_;
boost::asio::ip::udp::socket socket_;
};

#include <sstream>

int main() {
std::ostringstream oss;
boost::posix_time::ptime ptime = boost::posix_time::second_clock::local_time();
boost::asio::ip::address_v4 addr = boost::asio::ip::address_v4::from_string( "192.168.1.1" );
oss << get_pri_part( log_audit, notice ) << get_head_part( ptime, addr )
<< get_msg_part( "tag", "message" );
boost::asio::io_service io_service;
syslog_transfer st( io_service );
try {
st.connect( "localhost", "514" );
st.transfer( oss.str() );
} catch( std::exception& e ) {
std::cerr << e.what() << std::endl;
}
return 0;
}

ファイルの追加は、どこぞにアップしてリンクするしかないのかな?

追記:いまどき void main は無いだろ・・・と、from_string の部分のバグを修正しました。

0 件のコメント: