Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * network_logger.cpp - Fawkes network logger 00004 * 00005 * Created: Sat Dec 15 00:48:52 2007 (after I5 xmas party) 00006 * Copyright 2006-2007 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <netcomm/utils/network_logger.h> 00025 00026 #include <core/threading/mutex.h> 00027 #include <netcomm/fawkes/component_ids.h> 00028 #include <netcomm/fawkes/hub.h> 00029 #include <netcomm/utils/ntoh64.h> 00030 00031 #include <sys/time.h> 00032 #include <time.h> 00033 #include <netinet/in.h> 00034 #include <cstring> 00035 #include <cstdlib> 00036 #include <cstdio> 00037 00038 namespace fawkes { 00039 00040 void 00041 NetworkLoggerMessageContent::serialize() 00042 { 00043 } 00044 00045 00046 /** @class NetworkLogger <netcomm/utils/network_logger.h> 00047 * Interface for logging to network clients. 00048 * The NetwokLogger will pipe all output to clients that subscribed for log 00049 * messages. 00050 * @author Tim Niemueller 00051 */ 00052 00053 /** Constructor. 00054 * @param hub FawkesNetworkHub to use to send and receive messages 00055 * @param log_level minimum level to log 00056 */ 00057 NetworkLogger::NetworkLogger(FawkesNetworkHub *hub, LogLevel log_level) 00058 : Logger(log_level), 00059 FawkesNetworkHandler(FAWKES_CID_NETWORKLOGGER) 00060 { 00061 this->hub = hub; 00062 00063 hub->add_handler(this); 00064 } 00065 00066 00067 /** Destructor. */ 00068 NetworkLogger::~NetworkLogger() 00069 { 00070 hub->remove_handler(this); 00071 } 00072 00073 00074 void 00075 NetworkLogger::send_message(Logger::LogLevel level, struct timeval *t, 00076 const char *component, bool is_exception, 00077 const char *format, va_list va) 00078 { 00079 struct timeval now; 00080 if ( t == NULL ) { 00081 gettimeofday(&now, NULL); 00082 t = &now; 00083 } 00084 00085 NetworkLoggerMessageContent *content = new NetworkLoggerMessageContent(level, t, 00086 component, 00087 is_exception, 00088 format, va); 00089 00090 for ( __ssit = __subscribers.begin(); __ssit != __subscribers.end(); ++__ssit) { 00091 NetworkLoggerMessageContent *content_copy = new NetworkLoggerMessageContent(content); 00092 try { 00093 hub->send(*__ssit, FAWKES_CID_NETWORKLOGGER, MSGTYPE_LOGMESSAGE, content_copy); 00094 } catch (Exception &e) { 00095 // Boom, can't do anything about it, logging could cause infinite loop... 00096 } 00097 } 00098 00099 delete content; 00100 } 00101 00102 00103 void 00104 NetworkLogger::send_message(Logger::LogLevel level, struct timeval *t, 00105 const char *component, bool is_exception, 00106 const char *message) 00107 { 00108 struct timeval now; 00109 if ( t == NULL ) { 00110 gettimeofday(&now, NULL); 00111 t = &now; 00112 } 00113 00114 NetworkLoggerMessageContent *content = new NetworkLoggerMessageContent(level, t, 00115 component, 00116 is_exception, 00117 message); 00118 00119 for ( __ssit = __subscribers.begin(); __ssit != __subscribers.end(); ++__ssit) { 00120 NetworkLoggerMessageContent *content_copy = new NetworkLoggerMessageContent(content); 00121 try { 00122 hub->send(*__ssit, FAWKES_CID_NETWORKLOGGER, MSGTYPE_LOGMESSAGE, content_copy); 00123 } catch (Exception &e) { 00124 // Boom, can't do anything about it, logging could cause infinite loop... 00125 } 00126 } 00127 00128 delete content; 00129 } 00130 00131 00132 void 00133 NetworkLogger::vlog_debug(const char *component, const char *format, va_list va) 00134 { 00135 if ((log_level <= LL_DEBUG) && (! __subscribers.empty()) ) { 00136 __subscribers.lock(); 00137 send_message(LL_DEBUG, NULL, component, /* exception? */ false, format, va); 00138 __subscribers.unlock(); 00139 } 00140 } 00141 00142 00143 void 00144 NetworkLogger::vlog_info(const char *component, const char *format, va_list va) 00145 { 00146 if ((log_level <= LL_INFO) && (! __subscribers.empty()) ) { 00147 __subscribers.lock(); 00148 send_message(LL_INFO, NULL, component, /* exception? */ false, format, va); 00149 __subscribers.unlock(); 00150 } 00151 } 00152 00153 00154 void 00155 NetworkLogger::vlog_warn(const char *component, const char *format, va_list va) 00156 { 00157 if ((log_level <= LL_WARN) && (! __subscribers.empty()) ) { 00158 __subscribers.lock(); 00159 send_message(LL_WARN, NULL, component, /* exception? */ false, format, va); 00160 __subscribers.unlock(); 00161 } 00162 } 00163 00164 00165 void 00166 NetworkLogger::vlog_error(const char *component, const char *format, va_list va) 00167 { 00168 if ((log_level <= LL_ERROR) && (! __subscribers.empty()) ) { 00169 __subscribers.lock(); 00170 send_message(LL_ERROR, NULL, component, /* exception? */ false, format, va); 00171 __subscribers.unlock(); 00172 } 00173 } 00174 00175 00176 void 00177 NetworkLogger::log_debug(const char *component, const char *format, ...) 00178 { 00179 va_list arg; 00180 va_start(arg, format); 00181 vlog_debug(component, format, arg); 00182 va_end(arg); 00183 } 00184 00185 00186 void 00187 NetworkLogger::log_info(const char *component, const char *format, ...) 00188 { 00189 va_list arg; 00190 va_start(arg, format); 00191 vlog_info(component, format, arg); 00192 va_end(arg); 00193 } 00194 00195 00196 void 00197 NetworkLogger::log_warn(const char *component, const char *format, ...) 00198 { 00199 va_list arg; 00200 va_start(arg, format); 00201 vlog_warn(component, format, arg); 00202 va_end(arg); 00203 } 00204 00205 00206 void 00207 NetworkLogger::log_error(const char *component, const char *format, ...) 00208 { 00209 va_list arg; 00210 va_start(arg, format); 00211 vlog_error(component, format, arg); 00212 va_end(arg); 00213 } 00214 00215 00216 void 00217 NetworkLogger::log_debug(const char *component, Exception &e) 00218 { 00219 if ((log_level <= LL_DEBUG) && (! __subscribers.empty()) ) { 00220 __subscribers.lock(); 00221 for (Exception::iterator i = e.begin(); i != e.end(); ++i) { 00222 send_message(LL_DEBUG, NULL, component, /* exception? */ true, *i); 00223 } 00224 __subscribers.unlock(); 00225 } 00226 } 00227 00228 void 00229 NetworkLogger::log_info(const char *component, Exception &e) 00230 { 00231 if ((log_level <= LL_INFO) && (! __subscribers.empty()) ) { 00232 __subscribers.lock(); 00233 for (Exception::iterator i = e.begin(); i != e.end(); ++i) { 00234 send_message(LL_INFO, NULL, component, /* exception? */ true, *i); 00235 } 00236 __subscribers.unlock(); 00237 } 00238 } 00239 00240 00241 void 00242 NetworkLogger::log_warn(const char *component, Exception &e) 00243 { 00244 if ((log_level <= LL_WARN) && (! __subscribers.empty()) ) { 00245 __subscribers.lock(); 00246 for (Exception::iterator i = e.begin(); i != e.end(); ++i) { 00247 send_message(LL_WARN, NULL, component, /* exception? */ true, *i); 00248 } 00249 __subscribers.unlock(); 00250 } 00251 } 00252 00253 00254 void 00255 NetworkLogger::log_error(const char *component, Exception &e) 00256 { 00257 if ((log_level <= LL_ERROR) && (! __subscribers.empty()) ) { 00258 __subscribers.lock(); 00259 for (Exception::iterator i = e.begin(); i != e.end(); ++i) { 00260 send_message(LL_ERROR, NULL, component, /* exception? */ true, *i); 00261 } 00262 __subscribers.unlock(); 00263 } 00264 } 00265 00266 00267 00268 00269 void 00270 NetworkLogger::vtlog_debug(struct timeval *t, const char *component, 00271 const char *format, va_list va) 00272 { 00273 if ((log_level <= LL_DEBUG) && (! __subscribers.empty()) ) { 00274 __subscribers.lock(); 00275 send_message(LL_DEBUG, t, component, /* exception? */ false, format, va); 00276 __subscribers.unlock(); 00277 } 00278 } 00279 00280 00281 void 00282 NetworkLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va) 00283 { 00284 if ((log_level <= LL_INFO) && (! __subscribers.empty()) ) { 00285 __subscribers.lock(); 00286 send_message(LL_INFO, t, component, /* exception? */ false, format, va); 00287 __subscribers.unlock(); 00288 } 00289 } 00290 00291 00292 void 00293 NetworkLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va) 00294 { 00295 if ((log_level <= LL_WARN) && (! __subscribers.empty()) ) { 00296 __subscribers.lock(); 00297 send_message(LL_WARN, t, component, /* exception? */ false, format, va); 00298 __subscribers.unlock(); 00299 } 00300 } 00301 00302 00303 void 00304 NetworkLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va) 00305 { 00306 if ((log_level <= LL_ERROR) && (! __subscribers.empty()) ) { 00307 __subscribers.lock(); 00308 send_message(LL_ERROR, t, component, /* exception? */ false, format, va); 00309 __subscribers.unlock(); 00310 } 00311 } 00312 00313 00314 void 00315 NetworkLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...) 00316 { 00317 va_list arg; 00318 va_start(arg, format); 00319 vtlog_debug(t, component, format, arg); 00320 va_end(arg); 00321 } 00322 00323 00324 void 00325 NetworkLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...) 00326 { 00327 va_list arg; 00328 va_start(arg, format); 00329 vtlog_info(t, component, format, arg); 00330 va_end(arg); 00331 } 00332 00333 00334 void 00335 NetworkLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...) 00336 { 00337 va_list arg; 00338 va_start(arg, format); 00339 vtlog_warn(t, component, format, arg); 00340 va_end(arg); 00341 } 00342 00343 00344 void 00345 NetworkLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...) 00346 { 00347 va_list arg; 00348 va_start(arg, format); 00349 vtlog_error(t, component, format, arg); 00350 va_end(arg); 00351 } 00352 00353 00354 void 00355 NetworkLogger::tlog_debug(struct timeval *t, const char *component, Exception &e) 00356 { 00357 if ((log_level <= LL_DEBUG) && (! __subscribers.empty()) ) { 00358 __subscribers.lock(); 00359 for (Exception::iterator i = e.begin(); i != e.end(); ++i) { 00360 send_message(LL_DEBUG, t, component, /* exception? */ true, *i); 00361 } 00362 __subscribers.unlock(); 00363 } 00364 } 00365 00366 void 00367 NetworkLogger::tlog_info(struct timeval *t, const char *component, Exception &e) 00368 { 00369 if ((log_level <= LL_INFO) && (! __subscribers.empty()) ) { 00370 __subscribers.lock(); 00371 for (Exception::iterator i = e.begin(); i != e.end(); ++i) { 00372 send_message(LL_INFO, t, component, /* exception? */ true, *i); 00373 } 00374 __subscribers.unlock(); 00375 } 00376 } 00377 00378 00379 void 00380 NetworkLogger::tlog_warn(struct timeval *t, const char *component, Exception &e) 00381 { 00382 if ((log_level <= LL_WARN) && (! __subscribers.empty()) ) { 00383 __subscribers.lock(); 00384 for (Exception::iterator i = e.begin(); i != e.end(); ++i) { 00385 send_message(LL_WARN, t, component, /* exception? */ true, *i); 00386 } 00387 __subscribers.unlock(); 00388 } 00389 } 00390 00391 00392 void 00393 NetworkLogger::tlog_error(struct timeval *t, const char *component, Exception &e) 00394 { 00395 if ((log_level <= LL_ERROR) && (! __subscribers.empty()) ) { 00396 __subscribers.lock(); 00397 for (Exception::iterator i = e.begin(); i != e.end(); ++i) { 00398 send_message(LL_ERROR, t, component, /* exception? */ true, *i); 00399 } 00400 __subscribers.unlock(); 00401 } 00402 } 00403 00404 00405 void 00406 NetworkLogger::handle_network_message(FawkesNetworkMessage *msg) 00407 { 00408 if ( (msg->cid() == FAWKES_CID_NETWORKLOGGER) && 00409 (msg->msgid() == MSGTYPE_SUBSCRIBE) ) { 00410 __subscribers.lock(); 00411 __subscribers.push_back(msg->clid()); 00412 __subscribers.sort(); 00413 __subscribers.unique(); 00414 __subscribers.unlock(); 00415 } 00416 } 00417 00418 void 00419 NetworkLogger::client_connected(unsigned int clid) 00420 { 00421 } 00422 00423 00424 void 00425 NetworkLogger::client_disconnected(unsigned int clid) 00426 { 00427 __subscribers.remove_locked(clid); 00428 } 00429 00430 00431 /** @class NetworkLoggerMessageContent <netcomm/utils/network_logger.h> 00432 * Message sent over the network with a log message. 00433 * Contains a buffer with a small header and two null-terminated strings, the first 00434 * being the component and the second being the real message. 00435 * @author Tim Niemueller 00436 */ 00437 00438 00439 /** Constructor. 00440 * @param log_level Log level 00441 * @param t time 00442 * @param component component string 00443 * @param is_exception true if this message originates from an exception, false otherwise 00444 * @param format message string format 00445 * @param va va_list containing the arguments for the given format 00446 */ 00447 NetworkLoggerMessageContent::NetworkLoggerMessageContent(Logger::LogLevel log_level, 00448 struct timeval *t, 00449 const char *component, 00450 bool is_exception, 00451 const char *format, va_list va) 00452 { 00453 char *tmp = NULL; 00454 int tmplen; 00455 if ( (tmplen = vasprintf(&tmp, format, va)) != -1 ) { 00456 _payload_size = sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + tmplen + 2; 00457 _payload = calloc(1, _payload_size); 00458 __own_payload = true; 00459 header = (NetworkLogger::network_logger_header_t *)_payload; 00460 header->log_level = log_level; 00461 header->exception = is_exception ? 1 : 0; 00462 header->time_sec = hton64(t->tv_sec); 00463 header->time_usec = htonl(t->tv_usec); 00464 copy_payload(sizeof(NetworkLogger::network_logger_header_t), component, strlen(component)); 00465 copy_payload(sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + 1, tmp, tmplen); 00466 __component = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t); 00467 __message = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + 1; 00468 free(tmp); 00469 } 00470 } 00471 00472 00473 /** Constructor. 00474 * @param log_level Log level 00475 * @param t time 00476 * @param component component string 00477 * @param is_exception true if this message originates from an exception, false otherwise 00478 * @param message message string. 00479 */ 00480 NetworkLoggerMessageContent::NetworkLoggerMessageContent(Logger::LogLevel log_level, 00481 struct timeval *t, 00482 const char *component, 00483 bool is_exception, 00484 const char *message) 00485 { 00486 _payload_size = sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + strlen(message) + 2; 00487 _payload = calloc(1, _payload_size); 00488 __own_payload = true; 00489 header = (NetworkLogger::network_logger_header_t *)_payload; 00490 header->log_level = log_level; 00491 header->exception = is_exception ? 1 : 0; 00492 header->time_sec = hton64(t->tv_sec); 00493 header->time_usec = htonl(t->tv_usec); 00494 copy_payload(sizeof(NetworkLogger::network_logger_header_t), component, strlen(component)); 00495 copy_payload(sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + 1, message, strlen(message)); 00496 __component = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t); 00497 __message = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + 1; 00498 } 00499 00500 00501 /** Copy constructor. 00502 * @param content content to copy 00503 */ 00504 NetworkLoggerMessageContent::NetworkLoggerMessageContent(const NetworkLoggerMessageContent *content) 00505 { 00506 _payload_size = content->_payload_size; 00507 _payload = malloc(_payload_size); 00508 __own_payload = true; 00509 memcpy(_payload, content->_payload, _payload_size); 00510 header = (NetworkLogger::network_logger_header_t *)_payload; 00511 __component = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t); 00512 __message = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t) + strlen(__component) + 1; 00513 } 00514 00515 00516 /** Message parsing constructor. 00517 * To be used with FawkesNetworkMessage::msgc(). 00518 * @param component_id component ID 00519 * @param msg_id message ID 00520 * @param payload payload 00521 * @param payload_size payload size 00522 */ 00523 NetworkLoggerMessageContent::NetworkLoggerMessageContent(unsigned int component_id, 00524 unsigned int msg_id, 00525 void *payload, size_t payload_size) 00526 { 00527 if ( component_id != FAWKES_CID_NETWORKLOGGER ) { 00528 throw TypeMismatchException("Wrong CID, expected FAWKES_CID_NETWORKLOGGER"); 00529 } 00530 00531 _payload = payload; 00532 _payload_size = payload_size; 00533 __own_payload = false; 00534 header = (NetworkLogger::network_logger_header_t *)_payload; 00535 __component = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t); 00536 __message = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t) + strlen(__component) + 1; 00537 } 00538 00539 /** Destructor. */ 00540 NetworkLoggerMessageContent::~NetworkLoggerMessageContent() 00541 { 00542 if (__own_payload) free(_payload); 00543 } 00544 00545 /** Get time. 00546 * @return time of the log message 00547 */ 00548 struct timeval 00549 NetworkLoggerMessageContent::get_time() const 00550 { 00551 struct timeval rv; 00552 rv.tv_sec = (time_t)ntoh64(header->time_sec); 00553 rv.tv_usec = ntohl(header->time_usec); 00554 return rv; 00555 } 00556 00557 00558 /** Get component. 00559 * @return component string 00560 */ 00561 const char * 00562 NetworkLoggerMessageContent::get_component() const 00563 { 00564 return __component; 00565 } 00566 00567 00568 /** Get message. 00569 * @return message string 00570 */ 00571 const char * 00572 NetworkLoggerMessageContent::get_message() const 00573 { 00574 return __message; 00575 } 00576 00577 00578 /** Log level. 00579 * @return log level. 00580 */ 00581 Logger::LogLevel 00582 NetworkLoggerMessageContent::get_loglevel() const 00583 { 00584 return (Logger::LogLevel)header->log_level; 00585 } 00586 00587 00588 /** Check if message was generated by exception. 00589 * @return true if message was generated by exception, false otherwise 00590 */ 00591 bool 00592 NetworkLoggerMessageContent::is_exception() const 00593 { 00594 return (header->exception == 1); 00595 } 00596 00597 } // end namespace fawkes