2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <log4cxx/spi/loggingevent.h>
19 #include <log4cxx/ndc.h>
21 #include <log4cxx/level.h>
22 #include <log4cxx/helpers/loglog.h>
23 #include <log4cxx/helpers/system.h>
24 #include <log4cxx/helpers/socket.h>
28 #include <log4cxx/helpers/aprinitializer.h>
29 #include <log4cxx/helpers/threadspecificdata.h>
30 #include <log4cxx/helpers/transcoder.h>
33 #include <apr_portable.h>
34 #include <apr_strings.h>
35 #include <log4cxx/helpers/stringhelper.h>
36 #include <log4cxx/helpers/objectoutputstream.h>
37 #include <log4cxx/helpers/bytebuffer.h>
38 #include <log4cxx/logger.h>
39 #include <log4cxx/private/log4cxx_private.h>
41 using namespace log4cxx;
42 using namespace log4cxx::spi;
43 using namespace log4cxx::helpers;
45 IMPLEMENT_LOG4CXX_OBJECT(LoggingEvent)
49 // Accessor for start time.
51 log4cxx_time_t LoggingEvent::getStartTime() {
52 return log4cxx::helpers::APRInitializer::initialize();
55 LoggingEvent::LoggingEvent() :
59 ndcLookupRequired(true),
60 mdcCopyLookupRequired(true),
65 LoggingEvent::LoggingEvent(
66 const LogString& logger1, const LevelPtr& level1,
67 const LogString& message1, const LocationInfo& locationInfo1) :
73 ndcLookupRequired(true),
74 mdcCopyLookupRequired(true),
76 timeStamp(apr_time_now()),
77 locationInfo(locationInfo1),
78 threadName(getCurrentThreadName()) {
81 LoggingEvent::~LoggingEvent()
88 bool LoggingEvent::getNDC(LogString& dest) const
92 ndcLookupRequired = false;
95 ndc = new LogString(val);
105 bool LoggingEvent::getMDC(const LogString& key, LogString& dest) const
107 // Note the mdcCopy is used if it exists. Otherwise we use the MDC
108 // that is associated with the thread.
109 if (mdcCopy != 0 && !mdcCopy->empty())
111 MDC::Map::const_iterator it = mdcCopy->find(key);
113 if (it != mdcCopy->end())
115 if (!it->second.empty())
117 dest.append(it->second);
123 return MDC::get(key, dest);
127 LoggingEvent::KeySet LoggingEvent::getMDCKeySet() const
129 LoggingEvent::KeySet set;
131 if (mdcCopy != 0 && !mdcCopy->empty())
133 MDC::Map::const_iterator it;
134 for (it = mdcCopy->begin(); it != mdcCopy->end(); it++)
136 set.push_back(it->first);
142 ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
144 MDC::Map& m = data->getMap();
146 for(MDC::Map::const_iterator it = m.begin(); it != m.end(); it++) {
147 set.push_back(it->first);
155 void LoggingEvent::getMDCCopy() const
157 if(mdcCopyLookupRequired)
159 mdcCopyLookupRequired = false;
160 // the clone call is required for asynchronous logging.
161 ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
163 mdcCopy = new MDC::Map(data->getMap());
165 mdcCopy = new MDC::Map();
170 bool LoggingEvent::getProperty(const LogString& key, LogString& dest) const
177 std::map<LogString, LogString>::const_iterator it = properties->find(key);
179 if (it != properties->end())
181 dest.append(it->second);
188 LoggingEvent::KeySet LoggingEvent::getPropertyKeySet() const
190 LoggingEvent::KeySet set;
194 std::map<LogString, LogString>::const_iterator it;
195 for (it = properties->begin(); it != properties->end(); it++)
197 set.push_back(it->first);
205 const LogString LoggingEvent::getCurrentThreadName() {
209 DWORD threadId = GetCurrentThreadId();
210 apr_snprintf(result, sizeof(result), LOG4CXX_WIN32_THREAD_FMTSPEC, threadId);
212 // apr_os_thread_t encoded in HEX takes needs as many characters
213 // as two times the size of the type, plus an additional null byte.
214 char result[sizeof(apr_os_thread_t) * 3 + 10];
215 apr_os_thread_t threadId = apr_os_thread_current();
216 apr_snprintf(result, sizeof(result), LOG4CXX_APR_THREAD_FMTSPEC, (void*) &threadId);
218 LOG4CXX_DECODE_CHAR(str, (const char*) result);
221 return LOG4CXX_STR("0x00000000");
226 void LoggingEvent::setProperty(const LogString& key, const LogString& value)
230 properties = new std::map<LogString, LogString>;
233 (*properties)[key] = value;
238 void LoggingEvent::writeProlog(ObjectOutputStream& os, Pool& p) {
239 unsigned char classDesc[] = {
241 0x6F, 0x72, 0x67, 0x2E, 0x61, 0x70, 0x61, 0x63,
242 0x68, 0x65, 0x2E, 0x6C, 0x6F, 0x67, 0x34, 0x6A,
243 0x2E, 0x73, 0x70, 0x69, 0x2E, 0x4C, 0x6F, 0x67,
244 0x67, 0x69, 0x6E, 0x67, 0x45, 0x76, 0x65, 0x6E,
245 0x74, 0xF3, 0xF2, 0xB9, 0x23, 0x74, 0x0B, 0xB5,
246 0x3F, 0x03, 0x00, 0x0A, 0x5A, 0x00, 0x15, 0x6D,
247 0x64, 0x63, 0x43, 0x6F, 0x70, 0x79, 0x4C, 0x6F,
248 0x6F, 0x6B, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75,
249 0x69, 0x72, 0x65, 0x64, 0x5A, 0x00, 0x11, 0x6E,
250 0x64, 0x63, 0x4C, 0x6F, 0x6F, 0x6B, 0x75, 0x70,
251 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
252 0x4A, 0x00, 0x09, 0x74, 0x69, 0x6D, 0x65, 0x53,
253 0x74, 0x61, 0x6D, 0x70, 0x4C, 0x00, 0x0C, 0x63,
254 0x61, 0x74, 0x65, 0x67, 0x6F, 0x72, 0x79, 0x4E,
255 0x61, 0x6D, 0x65, 0x74, 0x00, 0x12, 0x4C, 0x6A,
256 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
257 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
258 0x4C, 0x00, 0x0C, 0x6C, 0x6F, 0x63, 0x61, 0x74,
259 0x69, 0x6F, 0x6E, 0x49, 0x6E, 0x66, 0x6F, 0x74,
260 0x00, 0x23, 0x4C, 0x6F, 0x72, 0x67, 0x2F, 0x61,
261 0x70, 0x61, 0x63, 0x68, 0x65, 0x2F, 0x6C, 0x6F,
262 0x67, 0x34, 0x6A, 0x2F, 0x73, 0x70, 0x69, 0x2F,
263 0x4C, 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
264 0x49, 0x6E, 0x66, 0x6F, 0x3B, 0x4C, 0x00, 0x07,
265 0x6D, 0x64, 0x63, 0x43, 0x6F, 0x70, 0x79, 0x74,
266 0x00, 0x15, 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F,
267 0x75, 0x74, 0x69, 0x6C, 0x2F, 0x48, 0x61, 0x73,
268 0x68, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3B, 0x4C,
269 0x00, 0x03, 0x6E, 0x64, 0x63,
270 0x74, 0x00, 0x12, 0x4C, 0x6A,
271 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
272 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
273 0x4C, 0x00, 0x0F, 0x72, 0x65, 0x6E,
274 0x64, 0x65, 0x72, 0x65, 0x64, 0x4D, 0x65, 0x73,
275 0x73, 0x61, 0x67, 0x65,
276 0x74, 0x00, 0x12, 0x4C, 0x6A,
277 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
278 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
279 0x4C, 0x00, 0x0A, 0x74, 0x68, 0x72, 0x65,
280 0x61, 0x64, 0x4E, 0x61, 0x6D, 0x65,
281 0x74, 0x00, 0x12, 0x4C, 0x6A,
282 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
283 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
284 0x4C, 0x00, 0x0D, 0x74, 0x68,
285 0x72, 0x6F, 0x77, 0x61, 0x62, 0x6C, 0x65, 0x49,
286 0x6E, 0x66, 0x6F, 0x74, 0x00, 0x2B, 0x4C, 0x6F,
287 0x72, 0x67, 0x2F, 0x61, 0x70, 0x61, 0x63, 0x68,
288 0x65, 0x2F, 0x6C, 0x6F, 0x67, 0x34, 0x6A, 0x2F,
289 0x73, 0x70, 0x69, 0x2F, 0x54, 0x68, 0x72, 0x6F,
290 0x77, 0x61, 0x62, 0x6C, 0x65, 0x49, 0x6E, 0x66,
291 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E,
294 os.writeProlog("org.apache.log4j.spi.LoggingEvent",
295 8, (char *) classDesc, sizeof(classDesc), p);
298 void LoggingEvent::write(helpers::ObjectOutputStream& os, Pool& p) const {
300 // mdc and ndc lookup required should always be false
301 char lookupsRequired[] = { 0, 0 };
302 os.writeBytes(lookupsRequired, sizeof(lookupsRequired), p);
303 os.writeLong(timeStamp/1000, p);
304 os.writeObject(logger, p);
305 locationInfo.write(os, p);
306 if (mdcCopy == 0 || mdcCopy->size() == 0) {
309 os.writeObject(*mdcCopy, p);
314 os.writeObject(*ndc, p);
316 os.writeObject(message, p);
317 os.writeObject(threadName, p);
320 os.writeByte(ObjectOutputStream::TC_BLOCKDATA, p);
321 os.writeByte(0x04, p);
322 os.writeInt(level->toInt(), p);
324 os.writeByte(ObjectOutputStream::TC_ENDBLOCKDATA, p);