1 /*
2 LinKNX KNX home automation platform
3 Copyright (C) 2007-2008 Jean-François Meessen <linknx@ouaye.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include "logger.h"
21
22 Logging* Logging::instance_m;
23
24 #ifdef HAVE_LOG4CPP
25
26 #include <log4cpp/BasicConfigurator.hh>
27 #include <log4cpp/PropertyConfigurator.hh>
28 #include <log4cpp/OstreamAppender.hh>
29 #include <log4cpp/FileAppender.hh>
30 #include <log4cpp/RollingFileAppender.hh>
31 #include <log4cpp/SimpleLayout.hh>
32 #include <log4cpp/PatternLayout.hh>
33
importXml(ticpp::Element * pConfig)34 void Logging::importXml(ticpp::Element* pConfig)
35 {
36 if (!pConfig) {
37 log4cpp::BasicConfigurator::configure();
38 }
39 else {
40 try{
41 conffile_m = pConfig->GetAttribute("config");
42 if (conffile_m.length()) {
43 log4cpp::PropertyConfigurator::configure(conffile_m); // throw (ConfigureFailure)
44 }
45 else {
46 output_m = pConfig->GetAttribute("output");
47 format_m = pConfig->GetAttribute("format");
48 level_m = pConfig->GetAttribute("level");
49 log4cpp::Appender* app = NULL;
50 if (output_m.length()) {
51 pConfig->GetAttributeOrDefault("maxfilesize", &maxSize_m, -1);
52 if (maxSize_m > 0) {
53 pConfig->GetAttributeOrDefault("maxfileindex", &maxIndex_m, 10);
54 app = new log4cpp::RollingFileAppender("RollingFileAppender", output_m, maxSize_m * 1024, maxIndex_m);
55 }
56 else
57 app = new log4cpp::FileAppender("FileAppender", output_m);
58 }
59 else
60 app = new log4cpp::OstreamAppender("ConsoleAppender", &std::cout);
61 if (format_m == "basic")
62 app->setLayout(new log4cpp::BasicLayout());
63 else if (format_m == "simple")
64 app->setLayout(new log4cpp::SimpleLayout());
65 else {
66 log4cpp::PatternLayout* patternLayout = new log4cpp::PatternLayout();
67 if (format_m == "")
68 patternLayout->setConversionPattern("%d [%5p] %c: %m%n");
69 else
70 patternLayout->setConversionPattern(format_m);
71 app->setLayout(patternLayout);
72 }
73 log4cpp::Priority::Value prio = log4cpp::Priority::INFO;
74 if (level_m != "")
75 prio = log4cpp::Priority::getPriorityValue(level_m);
76
77 log4cpp::Category& root = log4cpp::Category::getRoot();
78 root.setPriority(prio);
79
80 root.removeAllAppenders();
81 root.addAppender(app);
82 }
83 }
84 catch (log4cpp::ConfigureFailure ex) {
85 throw ticpp::Exception(ex.what());
86 }
87 catch (std::invalid_argument ex) {
88 throw ticpp::Exception(ex.what());
89 }
90 }
91 }
92
exportXml(ticpp::Element * pConfig)93 void Logging::exportXml(ticpp::Element* pConfig)
94 {
95 if (conffile_m != "")
96 {
97 pConfig->SetAttribute("config", conffile_m);
98 }
99 else
100 {
101 if (output_m != "")
102 {
103 pConfig->SetAttribute("output", output_m);
104 if (maxSize_m != -1)
105 {
106 pConfig->SetAttribute("maxfilesize", maxSize_m);
107 pConfig->SetAttribute("maxfileindex", maxIndex_m);
108 }
109 }
110 if (format_m != "")
111 pConfig->SetAttribute("format", format_m);
112 if (level_m != "")
113 pConfig->SetAttribute("level", level_m);
114 }
115 }
116
117 #else
118
119 #include <ctime>
120
121 int Logger::level_m;
122 bool Logger::timestamp_m;
123 NullStreamBuf Logger::nullStreamBuf_m;
124 std::ostream Logger::nullStream_m(&Logger::nullStreamBuf_m);
125
importXml(ticpp::Element * pConfig)126 void Logging::importXml(ticpp::Element* pConfig)
127 {
128 if (!pConfig) {
129 Logger::level_m = 20;
130 Logger::timestamp_m = true;
131 }
132 else {
133 // std::string output = pConfig->GetAttribute("output");
134 format_m = pConfig->GetAttribute("format");
135 level_m = pConfig->GetAttribute("level");
136 if (level_m == "" || level_m == "INFO")
137 Logger::level_m = 20;
138 else if (level_m == "NOTICE")
139 Logger::level_m = 30;
140 else if (level_m == "WARN")
141 Logger::level_m = 40;
142 else if (level_m == "ERROR")
143 Logger::level_m = 50;
144 else if (level_m == "DEBUG")
145 Logger::level_m = 10;
146
147 Logger::timestamp_m = (format_m != "simple");
148 }
149 }
150
exportXml(ticpp::Element * pConfig)151 void Logging::exportXml(ticpp::Element* pConfig)
152 {
153 if (format_m != "")
154 pConfig->SetAttribute("format", format_m);
155 if (level_m != "")
156 pConfig->SetAttribute("level", level_m);
157 }
158
getLoggerMap()159 Logger::LoggerMap_t* Logger::getLoggerMap() {
160 // This static local is used to avoid problems with
161 // initialization order of static object present in
162 // different compilation units
163 static LoggerMap_t* loggerMap = new LoggerMap_t();
164 return loggerMap;
165 }
166
getInstance(const char * cat)167 Logger& Logger::getInstance(const char* cat) {
168 LoggerMap_t* map = getLoggerMap();
169 LoggerMap_t::iterator it = map->find(cat);
170 Logger* logger;
171 if (it != map->end())
172 logger = it->second;
173 else {
174 logger = new Logger(cat);
175 map->insert(LoggerPair_t(cat, logger));
176 }
177 return *(logger);
178 }
179
180 DummyStream DummyStream::dummy;
181
Logger(const char * cat)182 Logger::Logger(const char* cat) : cat_m(cat) {
183 }
184
addPrefix(std::ostream & s,const char * level)185 std::ostream& Logger::addPrefix(std::ostream &s, const char* level) {
186 if (timestamp_m) {
187 time_t now;
188 struct tm * timeinfo;
189 char buffer [32];
190
191 time ( &now );
192 timeinfo = localtime ( &now );
193 strftime (buffer,sizeof(buffer),"%Y-%m-%d %X ",timeinfo);
194 s << buffer;
195 }
196 return s << level << cat_m << ": ";
197 }
198
errorStream()199 ErrStream Logger::errorStream() {
200 #ifdef LOG_SHOW_ERROR
201 if (level_m <= 50)
202 return addPrefix(std::cerr, "[ERROR] ");
203 else
204 return nullStream_m;
205 #else
206 return DummyStream::dummy;
207 #endif
208 }
209
warnStream()210 WarnStream Logger::warnStream() {
211 #ifdef LOG_SHOW_WARN
212 if (level_m <= 40)
213 return addPrefix(std::cerr, "[ WARN] ");
214 else
215 return nullStream_m;
216 #else
217 return DummyStream::dummy;
218 #endif
219 }
220
infoStream()221 LogStream Logger::infoStream() {
222 #ifdef LOG_SHOW_INFO
223 if (level_m <= 20)
224 return addPrefix(std::cout, "[ INFO] ");
225 else
226 return nullStream_m;
227 #else
228 return DummyStream::dummy;
229 #endif
230 }
231
debugStream()232 DbgStream Logger::debugStream() {
233 #ifdef LOG_SHOW_DEBUG
234 if (level_m <= 10)
235 return addPrefix(std::cout, "[DEBUG] ");
236 else
237 return nullStream_m;
238 #else
239 return DummyStream::dummy;
240 #endif
241 }
242
isDebugEnabled()243 bool Logger::isDebugEnabled() {
244 #ifdef LOG_SHOW_DEBUG
245 return (level_m <= 10);
246 #else
247 return false;
248 #endif
249 }
250
251 #endif
252
errorStream(const char * cat)253 ErrStream errorStream(const char* cat) { return Logger::getInstance(cat).errorStream(); };
warnStream(const char * cat)254 WarnStream warnStream(const char* cat) { return Logger::getInstance(cat).warnStream(); };
infoStream(const char * cat)255 LogStream infoStream(const char* cat) { return Logger::getInstance(cat).infoStream(); };
debugStream(const char * cat)256 DbgStream debugStream(const char* cat) { return Logger::getInstance(cat).debugStream(); };
isDebugEnabled(const char * cat)257 bool isDebugEnabled(const char* cat) { return Logger::getInstance(cat).isDebugEnabled(); };
258