4
* Copyright 2002, Bastiaan Bakker. All rights reserved.
6
* See the COPYING file for the terms of usage and distribution.
9
#include "PortabilityImpl.hh"
11
#include <log4shib/PatternLayout.hh>
12
#include <log4shib/Priority.hh>
13
#include <log4shib/NDC.hh>
14
#include <log4shib/TimeStamp.hh>
16
#ifdef LOG4SHIB_HAVE_SSTREAM
27
#ifdef LOG4SHIB_HAVE_INT64_T
28
#ifdef LOG4SHIB_HAVE_STDINT_H
30
#endif // LOG4SHIB_HAVE_STDINT_H
32
#ifdef LOG4SHIB_MISSING_INT64_OSTREAM_OP
33
/* workaround suggested at:
34
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q168440
39
std::ostream& operator<<(std::ostream& os, int64_t i) {
41
::sprintf(buf,"%I64d", i);
44
#endif // LOG4SHIB_MISSING_INT64_OSTREAM_OP
45
#endif // LOG4SHIB_HAVE_INT64_T
49
struct StringLiteralComponent : public PatternLayout::PatternComponent {
50
StringLiteralComponent(const std::string& literal) :
54
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
62
struct CategoryNameComponent : public PatternLayout::PatternComponent {
63
CategoryNameComponent(std::string specifier) {
64
if (specifier == "") {
67
#ifdef LOG4SHIB_HAVE_SSTREAM
68
std::istringstream s(specifier);
70
std::istrstream s(specifier.c_str());
76
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
77
if (_precision == -1) {
78
out << event.categoryName;
80
std::string::size_type begin = std::string::npos;
81
for(int i = 0; i < _precision; i++) {
82
begin = event.categoryName.rfind('.', begin - 2);
83
if (begin == std::string::npos) {
89
out << event.categoryName.substr(begin);
97
struct MessageComponent : public PatternLayout::PatternComponent {
98
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
103
struct NDCComponent : public PatternLayout::PatternComponent {
104
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
109
struct PriorityComponent : public PatternLayout::PatternComponent {
110
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
111
out << Priority::getPriorityName(event.priority);
115
struct ThreadNameComponent : public PatternLayout::PatternComponent {
116
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
117
out << event.threadName;
121
struct ProcessorTimeComponent : public PatternLayout::PatternComponent {
122
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
127
struct TimeStampComponent : public PatternLayout::PatternComponent {
128
static const char* const FORMAT_ISO8601;
129
static const char* const FORMAT_ABSOLUTE;
130
static const char* const FORMAT_DATE;
132
TimeStampComponent(std::string timeFormat) {
133
if ((timeFormat == "") || (timeFormat == "ISO8601")) {
134
timeFormat = FORMAT_ISO8601;
135
} else if (timeFormat == "ABSOLUTE") {
136
timeFormat = FORMAT_ABSOLUTE;
137
} else if (timeFormat == "DATE") {
138
timeFormat = FORMAT_DATE;
140
std::string::size_type pos = timeFormat.find("%l");
141
if (pos == std::string::npos) {
142
_printMillis = false;
143
_timeFormat1 = timeFormat;
146
_timeFormat1 = timeFormat.substr(0, pos);
147
_timeFormat2 = timeFormat.substr(pos + 2);
151
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
152
struct tm *currentTime;
153
time_t t = event.timeStamp.getSeconds();
154
#ifdef LOG4SHIB_HAVE_LOCALTIME_R
155
struct tm currentTime_var;
156
currentTime = ::localtime_r(&t, ¤tTime_var);
158
currentTime = std::localtime(&t);
161
std::string timeFormat;
163
std::ostringstream formatStream;
164
formatStream << _timeFormat1
165
<< std::setw(3) << std::setfill('0')
166
<< event.timeStamp.getMilliSeconds()
168
timeFormat = formatStream.str();
170
timeFormat = _timeFormat1;
172
std::strftime(formatted, sizeof(formatted), timeFormat.c_str(), currentTime);
177
std::string _timeFormat1;
178
std::string _timeFormat2;
182
const char* const TimeStampComponent::FORMAT_ISO8601 = "%Y-%m-%d %H:%M:%S,%l";
183
const char* const TimeStampComponent::FORMAT_ABSOLUTE = "%H:%M:%S,%l";
184
const char* const TimeStampComponent::FORMAT_DATE = "%d %b %Y %H:%M:%S,%l";
186
struct SecondsSinceEpochComponent : public PatternLayout::PatternComponent {
187
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
188
out << event.timeStamp.getSeconds();
192
struct MillisSinceEpochComponent : public PatternLayout::PatternComponent {
193
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
194
#ifdef LOG4SHIB_HAVE_INT64_T
195
int64_t t = event.timeStamp.getSeconds() -
196
TimeStamp::getStartTime().getSeconds();
198
t += event.timeStamp.getMilliSeconds() -
199
TimeStamp::getStartTime().getMilliSeconds();
203
double t = event.timeStamp.getSeconds() -
204
TimeStamp::getStartTime().getSeconds();
206
t += event.timeStamp.getMilliSeconds() -
207
TimeStamp::getStartTime().getMilliSeconds();
209
out << std::setiosflags(std::ios::fixed)
210
<< std::setprecision(0) << t;
215
struct FormatModifierComponent : public PatternLayout::PatternComponent {
216
FormatModifierComponent(PatternLayout::PatternComponent* component,
217
size_t minWidth, size_t maxWidth, bool alignLeft) :
218
_component(component) ,
221
_alignLeft(alignLeft) {
224
virtual ~FormatModifierComponent() {
228
virtual void append(std::ostringstream& out, const LoggingEvent& event) {
229
std::ostringstream s;
230
_component->append(s, event);
231
std::string msg = s.str();
232
if (_maxWidth > 0 && _maxWidth < msg.length()) {
233
msg.erase(_maxWidth);
235
std::string::size_type fillCount = _minWidth - msg.length();
236
if (_minWidth > msg.length()) {
238
out << msg << std::string(fillCount, ' ');
240
out << std::string(fillCount, ' ') << msg;
248
PatternLayout::PatternComponent* _component;
254
const char* PatternLayout::DEFAULT_CONVERSION_PATTERN = "%m%n";
255
const char* PatternLayout::SIMPLE_CONVERSION_PATTERN = "%p - %m%n";
256
const char* PatternLayout::BASIC_CONVERSION_PATTERN = "%R %p %c %x: %m%n";
257
const char* PatternLayout::TTCC_CONVERSION_PATTERN = "%r [%t] %p %c %x - %m%n";
259
PatternLayout::PatternLayout() {
261
setConversionPattern(DEFAULT_CONVERSION_PATTERN);
262
} catch(ConfigureFailure&) {
266
PatternLayout::~PatternLayout() {
267
clearConversionPattern();
270
void PatternLayout::clearConversionPattern() {
271
for(ComponentVector::const_iterator i = _components.begin();
272
i != _components.end(); ++i) {
276
_conversionPattern = "";
279
void PatternLayout::setConversionPattern(const std::string& conversionPattern) throw(ConfigureFailure) {
280
#ifdef LOG4SHIB_HAVE_SSTREAM
281
std::istringstream conversionStream(conversionPattern);
283
std::istrstream conversionStream(conversionPattern.c_str());
288
PatternLayout::PatternComponent* component = NULL;
291
clearConversionPattern();
292
while (conversionStream.get(ch)) {
297
conversionStream.get(ch2);
298
if ((ch2 == '-') || ((ch2 >= '0') && (ch2 <= '9'))) {
299
conversionStream.putback(ch2);
300
conversionStream >> minWidth;
301
conversionStream.get(ch2);
304
conversionStream >> maxWidth;
306
conversionStream.putback(ch2);
309
if (!conversionStream.get(ch)) {
310
std::ostringstream msg;
311
msg << "unterminated conversion specifier in '" << conversionPattern << "' at index " << conversionStream.tellg();
312
throw ConfigureFailure(msg.str());
314
std::string specPostfix = "";
318
if (conversionStream.get(ch2)) {
320
while(conversionStream.get(ch2) && (ch2 != '}'))
323
conversionStream.putback(ch2);
332
component = new MessageComponent();
336
std::ostringstream endline;
337
endline << std::endl;
338
literal += endline.str();
342
component = new CategoryNameComponent(specPostfix);
345
component = new TimeStampComponent(specPostfix);
348
component = new PriorityComponent();
351
component = new MillisSinceEpochComponent();
354
component = new SecondsSinceEpochComponent();
357
component = new ThreadNameComponent();
360
component = new ProcessorTimeComponent();
363
component = new NDCComponent();
366
std::ostringstream msg;
367
msg << "unknown conversion specifier '" << ch << "' in '" << conversionPattern << "' at index " << conversionStream.tellg();
368
throw ConfigureFailure(msg.str());
371
if (!literal.empty()) {
372
_components.push_back(new StringLiteralComponent(literal));
375
if ((minWidth != 0) || (maxWidth != 0)) {
376
component = new FormatModifierComponent(component, std::abs(minWidth), maxWidth, minWidth < 0);
380
_components.push_back(component);
387
if (!literal.empty()) {
388
_components.push_back(new StringLiteralComponent(literal));
391
_conversionPattern = conversionPattern;
394
std::string PatternLayout::getConversionPattern() const {
395
return _conversionPattern;
398
std::string PatternLayout::format(const LoggingEvent& event) {
399
std::ostringstream message;
401
for(ComponentVector::const_iterator i = _components.begin();
402
i != _components.end(); ++i) {
403
(*i)->append(message, event);
406
return message.str();