summaryrefslogtreecommitdiff
path: root/project2/common/logger.h
blob: 7f6e7a0ec6f954f5844e8f258e89bd9e4ea4757f (plain)
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
#ifndef LOGGER_H
#define LOGGER_H

#include <map>
#include <stdarg.h>
#include <stdlib.h>
#include <syslog.h> // Pulled in for easy client lookups of LOG_* priorties
#include <boost/intrusive_ptr.hpp>
#include <boost/format.hpp>
#include "intrusivePtrBase.h"
#include "genLoader.h"
#include <misc.h>

/// Base class for classes providing a logging facility
class LogDriverBase : public virtual IntrusivePtrBase {
	public:
		LogDriverBase();
		virtual ~LogDriverBase();

		virtual void message(int priority, const char * msg) const = 0;
};

class LogDriverLoader : public GenLoader<LogDriverBase, std::string> {
	public:
		virtual int loggerLevel() const = 0;
};

class Log {
	public:
		typedef boost::intrusive_ptr<LogDriverBase> LogDriverBasePtr;
		typedef std::map<LogDriverLoader *, LogDriverBasePtr> LogDrivers;

		Log();
		~Log();

		void setLoggerAt(LogDriverLoader *, int level);

		void message(int priority, const char * msg) const;
		void messagef(int priority, const char * msgfmt, ...) const __attribute__ ((format (printf, 3, 4)));
		template <typename... Args>
		void messagebf(int priority, const char * msgfmt, const Args & ... args) const {
			if (priority > lowestLevel) return;
			boost::shared_ptr<boost::format> fmt = getFormat(msgfmt);
			messagebf(priority, *fmt, args...);
		}
		void vmessagef(int priority, const char * msgfmt, va_list) const;

		static const char * priorityName(int priority); // Look up the priority as defined in syslog.h

	private:
		template <typename Arg, typename... OtherArgs>
		void messagebf(int priority, boost::format & f, const Arg & arg, const OtherArgs & ... otherargs) const {
			f % arg;
			messagebf(priority, f, otherargs...);
		}
		void messagebf(int priority, const boost::format & f) const;
		LogDrivers logs;
		int lowestLevel;
		int nextId;
};

class Logger {
	public:
		Log * operator->() const;
	private:
		static Log log;
};

template<typename LoggerType>
class LogDriverLoaderImpl : public LogDriverLoader::For<LoggerType, LogDriverLoader> {
	public:
		LogDriverLoaderImpl() :
			level(LoggerType::level)
		{
		}
		virtual void onConfigLoad() override {
			Logger()->setLoggerAt(this, level);
			if (level == -1) {
				instance.reset();
			}
		}
		inline LoggerType * create() const {
			if (!instance) {
				instance = new LoggerType();
			}
			return instance.get();
		}
		int loggerLevel() const {
			return level;
		}
		const int & level;
	private:
		mutable boost::intrusive_ptr<LoggerType> instance;
};
#define DECLARE_LOGGER_LOADER(N, T) \
	DECLARE_CUSTOM_COMPONENT_LOADER(N, T, LogDriverLoaderImpl<T>, LogDriverLoader);

#endif