00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00027
00028 #ifndef ICL_CORE_LOGGING_LOG_OUTPUT_STREAM_H_INCLUDED
00029 #define ICL_CORE_LOGGING_LOG_OUTPUT_STREAM_H_INCLUDED
00030
00031 #include <icl_core/BaseTypes.h>
00032 #include <icl_core/os_mem.h>
00033 #include <icl_core/List.h>
00034 #include <icl_core/Noncopyable.h>
00035 #include <icl_core/TimeStamp.h>
00036
00037 #ifdef _SYSTEM_LXRT_
00038 #define ICL_CORE_LOG_OUTPUT_STREAM_USE_FIXED_QUEUE
00039 #else
00040 # include <icl_core/Queue.h>
00041 #endif
00042
00043 #include "icl_core_logging/Constants.h"
00044 #include "icl_core_logging/ImportExport.h"
00045 #include "icl_core_logging/LoggingManager.h"
00046 #include "icl_core_logging/LogLevel.h"
00047 #include "icl_core_logging/Semaphore.h"
00048 #include "icl_core_logging/Thread.h"
00049
00050 namespace icl_core {
00051 namespace logging {
00052
00075 class ICL_CORE_LOGGING_IMPORT_EXPORT LogOutputStream : protected virtual icl_core::Noncopyable
00076 {
00077 public:
00088 LogOutputStream(const icl_core::String& name, const icl_core::String& config_prefix,
00089 icl_core::logging::LogLevel log_level, bool use_worker_thread = true);
00090
00091 virtual ~LogOutputStream();
00092
00097 void changeTimeFormat(const char* format) { m_time_format = format; }
00098
00130 void changeLogFormat(const char *format);
00131
00148 void push(icl_core::logging::LogLevel log_level, const char *log_stream_description,
00149 const char *filename, int line, const char *classname, const char *objectname,
00150 const char *function, const char *text);
00151
00153 void start();
00154
00158 void shutdown();
00159
00162 icl_core::logging::LogLevel getLogLevel() const { return m_log_level; }
00163
00166 void setLogLevel(icl_core::logging::LogLevel log_level) { m_log_level = log_level; }
00167
00173 icl_core::String name() const { return m_name; }
00174
00178 void printConfiguration() const;
00179
00181 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00182
00186 ICL_CORE_VC_DEPRECATE_STYLE void ChangeTimeFormat(const char* format) ICL_CORE_GCC_DEPRECATE_STYLE;
00187
00191 ICL_CORE_VC_DEPRECATE_STYLE void ChangeLogFormat(const char *format)
00192 ICL_CORE_GCC_DEPRECATE_STYLE;
00193
00197 ICL_CORE_VC_DEPRECATE_STYLE void Push(icl_core::logging::LogLevel log_level,
00198 const char *log_stream_description, const char *filename,
00199 int line, const char *classname, const char *objectname,
00200 const char *function, const char *text)
00201 ICL_CORE_GCC_DEPRECATE_STYLE;
00202
00206 ICL_CORE_VC_DEPRECATE_STYLE void Start() ICL_CORE_GCC_DEPRECATE_STYLE;
00207
00212 ICL_CORE_VC_DEPRECATE_STYLE void Shutdown() ICL_CORE_GCC_DEPRECATE_STYLE;
00213
00217 ICL_CORE_VC_DEPRECATE_STYLE_USE(LogOutputStream::getLogLevel)
00218 icl_core::logging::LogLevel LogLevel() const
00219 ICL_CORE_GCC_DEPRECATE_STYLE_USE(LogOutputStream::getLogLevel);
00220
00224 ICL_CORE_VC_DEPRECATE_STYLE void SetLogLevel(icl_core::logging::LogLevel log_level)
00225 ICL_CORE_GCC_DEPRECATE_STYLE;
00226
00230 ICL_CORE_VC_DEPRECATE_STYLE icl_core::String Name() const ICL_CORE_GCC_DEPRECATE_STYLE;
00231
00236 ICL_CORE_VC_DEPRECATE_STYLE void PrintConfiguration() const ICL_CORE_GCC_DEPRECATE_STYLE;
00237
00238 #endif
00239
00240
00241 protected:
00243 struct LogMessage
00244 {
00245 LogMessage(const icl_core::TimeStamp& timestamp = icl_core::TimeStamp(),
00246 icl_core::logging::LogLevel log_level = eLL_MUTE,
00247 const char *log_stream = "", const char *filename = "",
00248 size_t line = 0,
00249 const char *class_name = "", const char *object_name = "", const char *function_name = "",
00250 const char *message_text = "");
00251
00252 icl_core::TimeStamp timestamp;
00253 icl_core::logging::LogLevel log_level;
00254 char log_stream[cMAX_IDENTIFIER_LENGTH + 1];
00255 char filename[cMAX_DESCRIPTION_LENGTH + 1];
00256 size_t line;
00257 char class_name[cMAX_IDENTIFIER_LENGTH + 1];
00258 char object_name[cMAX_DESCRIPTION_LENGTH + 1];
00259 char function_name[cMAX_IDENTIFIER_LENGTH + 1];
00260 char message_text[cDEFAULT_LOG_SIZE + 1];
00261 };
00262
00265 LogOutputStream(const icl_core::String& name, icl_core::logging::LogLevel log_level,
00266 bool use_worker_thread = true);
00267
00268 private:
00269 friend class LoggingManager;
00270
00272 struct WorkerThread : public Thread, protected virtual icl_core::Noncopyable
00273 {
00274 #ifdef ICL_CORE_LOG_OUTPUT_STREAM_USE_FIXED_QUEUE
00275 WorkerThread(LogOutputStream *output_stream, size_t message_queue_size,
00276 icl_core::ThreadPriority priority);
00277 #else
00278 WorkerThread(LogOutputStream *output_stream, icl_core::ThreadPriority priority);
00279 #endif
00280 ~WorkerThread();
00281
00282 virtual void run();
00283
00284 #ifdef ICL_CORE_LOG_OUTPUT_STREAM_USE_FIXED_QUEUE
00285 void incrementIndex(size_t& index);
00286 bool isMessageQueueEmpty();
00287 bool isMessageQueueFull();
00288 #endif
00289
00290 LogOutputStream *m_output_stream;
00291
00292 #ifdef ICL_CORE_LOG_OUTPUT_STREAM_USE_FIXED_QUEUE
00293 LogMessage *m_message_queue;
00294 size_t m_message_queue_size;
00295 size_t m_message_queue_read_index;
00296 size_t m_message_queue_write_index;
00297 #else
00298 typedef icl_core::Queue<LogMessage> MessageQueue;
00299 MessageQueue m_message_queue;
00300 #endif
00301
00302 Semaphore *m_mutex;
00303 Semaphore *m_fill_count;
00304 };
00305 friend struct WorkerThread;
00306
00310 struct LogFormatEntry
00311 {
00312 enum EntryType
00313 {
00314 eT_TEXT,
00315 eT_CLASSNAME,
00316 eT_OBJECTNAME,
00317 eT_FUNCTION,
00318 eT_MESSAGE,
00319 eT_FILENAME,
00320 eT_LINE,
00321 eT_LEVEL,
00322 eT_STREAM,
00323 eT_TIMESTAMP,
00324 eT_TIMESTAMP_MS
00325 };
00326
00327 LogFormatEntry()
00328 : type(eT_TEXT), width(0)
00329 {
00330 icl_core::os::memset(text, 0, 100);
00331 icl_core::os::memset(suffix, 0, 100);
00332 }
00333
00334 EntryType type;
00335 size_t width;
00336 char text[100];
00337 char suffix[100];
00338 };
00339
00345 virtual void onStart() { }
00353 virtual void pushImpl(const LogMessage& log_message);
00359 virtual void pushImpl(const std::string& log_line);
00365 virtual void onShutdown() { }
00366
00367 void parseLogFormat(const char *format);
00368
00369 icl_core::String m_name;
00370 icl_core::logging::LogLevel m_log_level;
00371 const char *m_time_format;
00372
00373 bool m_use_worker_thread;
00374 WorkerThread *m_worker_thread;
00375 Semaphore m_no_worker_thread_push_mutex;
00376
00377 Semaphore m_format_mutex;
00378 icl_core::List<LogFormatEntry> m_log_format;
00379 icl_core::List<LogFormatEntry> m_new_log_format;
00380
00381 static const icl_core::String m_default_log_format;
00382 static const icl_core::ThreadPriority m_default_worker_thread_priority;
00383 };
00384
00385 }
00386 }
00387
00388 #endif