Loggers!

closed account (3hM2Nwbp)
Everyone needs a little logging every now and then. Anyone else care to share their design?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
///@file Logger.hpp
#ifndef __LOGGER_HPP_INCLUDED__
#define __LOGGER_HPP_INCLUDED__

#include<iostream>

/// An enumeration of various logging categories
enum LogCategory
{
	LC_INFO,     /// Info	 - messages are sent to std::clog
	LC_ERROR,    /// Error	 - messages are sent to std::err
	LC_DEBUG,    /// Debug	 - messages are sent to std::cout
	LC_EXPLOIT   /// Exploit - messages are (temp) sent to std::cout
                     /// TODO: Send messages via IRC or Email
};

/**
 *	@class Logger
 *	@brief A simple logging utility, not a performance solution, but quick and easy.
 *	@author Luc
 *	@version 1
 */
class Logger
{
	public:

		/// Retrieves a logger instance of the specified category
		/**
		 *	@param category
		 *		The category to log under
		 *	@return
		 *		A logger instance of the specified category
		 *	@throw
		 *		This method may throw a std::logic_error if a logger of the specified category does not exist
		 *	@note
		 *		Any exceptional behavior can be prevented at compile-time.
		 */
		static Logger& getInstance(LogCategory category)
		{
			static Logger info(LC_INFO), error(LC_ERROR), debug(LC_DEBUG), exploit(LC_EXPLOIT);
			switch(category)
			{
				case LC_INFO:
					return info;				
				case LC_ERROR:
					return error;
				case LC_DEBUG:
					return debug;
				case LC_EXPLOIT:
					return exploit;
				default:
					throw std::logic_error("Logger::getInstance - No existing logger of the specified category exists.");
			}
		}

		/// Inserts the provided data into the specified logger's stream
		/**
		 *	@tparam T
		 *		The type of the data to insert
		 *	@param logger
		 *		The logger whose stream to use
		 *	@param data
		 *		The data to insert
		 *	@return
		 *		A reference to the specified logger is returned
		 *	@throw
		 *		This method may throw a std::bad_alloc if the stream insertion fails due to a low memory situation.
		 */
		template<typename T>
		friend Logger& operator<<(Logger& logger, const T& data)
		{
			logger.log(data);
			return logger;
		}

	private:

		/// Non-copyable
		Logger(const Logger& rhs);

		/// Non-assignable
		Logger operator=(const Logger& rhs);

		/// Constructs a Logger
		/**
		 *	@note
		 *		This class is intentionally not publicly constructable.
		 *	@param category
		 *		The type of logging that this Logger will do
		 *	@throw
		 *		This method may throw a std::bad_alloc if construction fails due to a low memory situation
		 */
		Logger(LogCategory category)
		 : category_(category)
		{
		
		}
		
		/// Logs the specified data in the way that is specified
		/**
		 *	@tparam T
		 *		The type of the data to log
		 *	@param data
		 *		The data to log
		 *	@throw
		 *		This method may throw a std::logic_error if a logger of the specified category does not exist<br>
		 *		or if the logging fails due to a low memory situation
		 */
		template<typename T>
		void log(const T& data)
		{
			switch(this->category_)
			{
				case LC_INFO:
					std::clog << data << std::flush;
					break;
				case LC_ERROR:
					std::cerr << data << std::flush;
					break;
				case LC_DEBUG:
					std::cout << data << std::flush;
					break;
				case LC_EXPLOIT:
					std::cout << data << std::flush;
					break;
				default:
					throw std::logic_error("Logger::log - No existing logger of the specified category exists.");
			}
		}

		/// The logging category that this logger covers
		LogCategory category_;
};

#endif 


1
2
3
4
5
6
#include "Logger.hpp"
int main()
{
    Logger::getInstance(LC_DEBUG) << "Hello Logging";
    return 0;
}
Last edited on
This does me for almost all instances.

1
2
3
4
5
6
7
8
9
10
typedef enum {lt_err, lt_info, ...} LogType;

std::string logPath(LogType l) {
..
..
}

boost::shared_ptr<std::ostream> logStream(LogType l) {
  return boost::shared_ptr<std::ostream>(new std::ofstream(logPath(l).c_str(), std::ios::app));
}
Last edited on
closed account (zb0S216C)
Luc Lieber wrote:
Everyone needs a little logging every now and then.

I manually write my own logs in text files. I really should integrate some sort of automatic logging system, but I don't really have the time to plan out a design.

I really like this chicken, and salad sandwich I'm eating.

Wazzak
I have been writing my log for ages (it supports Xml and plain text files, as well as ostreams and anything else which can output lines of text). However, even as I add more and more features to it, I am starting to wonder if I should just use Boost.Logging or log4cpp or something.

What are people's opinions on this matter?

EDIT: Also, my log class is not a singleton. I thought long and hard about this, but I am making all the classes in my library non singleton, with an optional "singletonised" version.
Last edited on
Topic archived. No new replies allowed.