Coverage Report

Created: 2025-07-01 06:08

/src/logging-log4cxx/src/main/cpp/htmllayout.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
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
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
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.
16
 */
17
18
#include <log4cxx/logstring.h>
19
#include <log4cxx/htmllayout.h>
20
#include <log4cxx/spi/loggingevent.h>
21
#include <log4cxx/helpers/optionconverter.h>
22
#include <log4cxx/level.h>
23
#include <log4cxx/helpers/transform.h>
24
#include <log4cxx/helpers/iso8601dateformat.h>
25
#include <log4cxx/helpers/stringhelper.h>
26
#include <log4cxx/helpers/transcoder.h>
27
#include <log4cxx/helpers/date.h>
28
29
using namespace LOG4CXX_NS;
30
using namespace LOG4CXX_NS::helpers;
31
using namespace LOG4CXX_NS::spi;
32
33
struct HTMLLayout::HTMLLayoutPrivate
34
{
35
  HTMLLayoutPrivate()
36
0
    : locationInfo(false)
37
0
    , title(LOG4CXX_STR("Log4cxx Log Messages"))
38
0
    , dateFormat()
39
0
    , expectedPatternLength(100)
40
0
    {}
41
42
  // Print no location info by default
43
  bool locationInfo; //= false
44
45
  LogString title;
46
47
  helpers::ISO8601DateFormat dateFormat;
48
49
  // Expected length of a formatted event excluding the message text
50
  size_t expectedPatternLength;
51
};
52
53
IMPLEMENT_LOG4CXX_OBJECT(HTMLLayout)
54
55
56
HTMLLayout::HTMLLayout()
57
0
  : m_priv(std::make_unique<HTMLLayoutPrivate>())
58
0
{
59
0
  m_priv->dateFormat.setTimeZone(TimeZone::getGMT());
60
0
  m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
61
0
}
Unexecuted instantiation: log4cxx::HTMLLayout::HTMLLayout()
Unexecuted instantiation: log4cxx::HTMLLayout::HTMLLayout()
62
63
0
HTMLLayout::~HTMLLayout() {}
64
65
66
void HTMLLayout::setOption(const LogString& option,
67
  const LogString& value)
68
0
{
69
70
0
  if (StringHelper::equalsIgnoreCase(option,
71
0
      LOG4CXX_STR("TITLE"), LOG4CXX_STR("title")))
72
0
  {
73
0
    setTitle(value);
74
0
  }
75
0
  else if (StringHelper::equalsIgnoreCase(option,
76
0
      LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
77
0
  {
78
0
    setLocationInfo(OptionConverter::toBoolean(value, false));
79
0
    m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
80
0
  }
81
0
}
82
83
void HTMLLayout::format(LogString& output,
84
  const spi::LoggingEventPtr& event,
85
  Pool& p) const
86
0
{
87
0
  output.reserve(m_priv->expectedPatternLength + event->getMessage().size());
88
0
  output.append(LOG4CXX_EOL);
89
0
  output.append(LOG4CXX_STR("<tr>"));
90
0
  output.append(LOG4CXX_EOL);
91
0
  output.append(LOG4CXX_STR("<td>"));
92
93
0
  m_priv->dateFormat.format(output, event->getTimeStamp(), p);
94
95
96
0
  output.append(LOG4CXX_STR("</td>"));
97
0
  output.append(LOG4CXX_EOL);
98
99
0
  output.append(LOG4CXX_STR("<td title=\""));
100
0
  LogString threadName(event->getThreadName());
101
0
  output.append(threadName);
102
0
  output.append(LOG4CXX_STR(" thread\">"));
103
0
  output.append(threadName);
104
0
  output.append(LOG4CXX_STR("</td>"));
105
0
  output.append(LOG4CXX_EOL);
106
107
0
  output.append(LOG4CXX_STR("<td title=\"Level\">"));
108
109
0
  if (event->getLevel()->equals(Level::getDebug()))
110
0
  {
111
0
    output.append(LOG4CXX_STR("<font color=\"#339933\">"));
112
0
    output.append(event->getLevel()->toString());
113
0
    output.append(LOG4CXX_STR("</font>"));
114
0
  }
115
0
  else if (event->getLevel()->isGreaterOrEqual(Level::getWarn()))
116
0
  {
117
0
    output.append(LOG4CXX_STR("<font color=\"#993300\"><strong>"));
118
0
    output.append(event->getLevel()->toString());
119
0
    output.append(LOG4CXX_STR("</strong></font>"));
120
0
  }
121
0
  else
122
0
  {
123
0
    output.append(event->getLevel()->toString());
124
0
  }
125
126
0
  output.append(LOG4CXX_STR("</td>"));
127
0
  output.append(LOG4CXX_EOL);
128
129
0
  output.append(LOG4CXX_STR("<td title=\""));
130
0
  output.append(event->getLoggerName());
131
0
  output.append(LOG4CXX_STR(" logger\">"));
132
0
  Transform::appendEscapingTags(output, event->getLoggerName());
133
0
  output.append(LOG4CXX_STR("</td>"));
134
0
  output.append(LOG4CXX_EOL);
135
136
0
  if (m_priv->locationInfo)
137
0
  {
138
0
    output.append(LOG4CXX_STR("<td>"));
139
0
    const LocationInfo& locInfo = event->getLocationInformation();
140
0
    LOG4CXX_DECODE_CHAR(fileName, locInfo.getFileName());
141
0
    Transform::appendEscapingTags(output, fileName);
142
0
    output.append(1, (logchar) 0x3A /* ':' */);
143
0
    int line = event->getLocationInformation().getLineNumber();
144
145
0
    if (line != 0)
146
0
    {
147
0
      StringHelper::toString(line, p, output);
148
0
    }
149
150
0
    output.append(LOG4CXX_STR("</td>"));
151
0
    output.append(LOG4CXX_EOL);
152
0
  }
153
154
0
  output.append(LOG4CXX_STR("<td title=\"Message\">"));
155
0
  Transform::appendEscapingTags(output, event->getRenderedMessage());
156
0
  output.append(LOG4CXX_STR("</td>"));
157
0
  output.append(LOG4CXX_EOL);
158
0
  output.append(LOG4CXX_STR("</tr>"));
159
0
  output.append(LOG4CXX_EOL);
160
161
0
  LogString ndcVal;
162
163
0
  if (event->getNDC(ndcVal))
164
0
  {
165
0
    output.append(LOG4CXX_STR("<tr><td bgcolor=\"#EEEEEE\" "));
166
0
    output.append(LOG4CXX_STR("style=\"font-size : xx-small;\" colspan=\"6\" "));
167
0
    output.append(LOG4CXX_STR("title=\"Nested Diagnostic Context\">"));
168
0
    output.append(LOG4CXX_STR("NDC: "));
169
0
    Transform::appendEscapingTags(output, ndcVal);
170
0
    output.append(LOG4CXX_STR("</td></tr>"));
171
0
    output.append(LOG4CXX_EOL);
172
0
  }
173
0
}
174
175
void HTMLLayout::appendHeader(LogString& output, Pool& p)
176
0
{
177
0
  output.append(LOG4CXX_STR("<!DOCTYPE HTML PUBLIC "));
178
0
  output.append(LOG4CXX_STR("\"-//W3C//DTD HTML 4.01 Transitional//EN\" "));
179
0
  output.append(LOG4CXX_STR("\"http://www.w3.org/TR/html4/loose.dtd\">"));
180
0
  output.append(LOG4CXX_EOL);
181
0
  output.append(LOG4CXX_STR("<html>"));
182
0
  output.append(LOG4CXX_EOL);
183
0
  output.append(LOG4CXX_STR("<head>"));
184
0
  output.append(LOG4CXX_EOL);
185
0
  output.append(LOG4CXX_STR("<title>"));
186
0
  output.append(m_priv->title);
187
0
  output.append(LOG4CXX_STR("</title>"));
188
0
  output.append(LOG4CXX_EOL);
189
0
  output.append(LOG4CXX_STR("<style type=\"text/css\">"));
190
0
  output.append(LOG4CXX_EOL);
191
0
  output.append(LOG4CXX_STR("<!--"));
192
0
  output.append(LOG4CXX_EOL);
193
0
  output.append(LOG4CXX_STR("body, table {font-family: arial,sans-serif; font-size: x-small;}"));
194
0
  output.append(LOG4CXX_EOL);
195
0
  output.append(LOG4CXX_STR("th {background: #336699; color: #FFFFFF; text-align: left;}"));
196
0
  output.append(LOG4CXX_EOL);
197
0
  output.append(LOG4CXX_STR("-->"));
198
0
  output.append(LOG4CXX_EOL);
199
0
  output.append(LOG4CXX_STR("</style>"));
200
0
  output.append(LOG4CXX_EOL);
201
0
  output.append(LOG4CXX_STR("</head>"));
202
0
  output.append(LOG4CXX_EOL);
203
0
  output.append(LOG4CXX_STR("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">"));
204
0
  output.append(LOG4CXX_EOL);
205
0
  output.append(LOG4CXX_STR("<hr size=\"1\" noshade>"));
206
0
  output.append(LOG4CXX_EOL);
207
0
  output.append(LOG4CXX_STR("Log session start time "));
208
209
0
  m_priv->dateFormat.format(output, Date::currentTime(), p);
210
211
0
  output.append(LOG4CXX_STR("<br>"));
212
0
  output.append(LOG4CXX_EOL);
213
0
  output.append(LOG4CXX_STR("<br>"));
214
0
  output.append(LOG4CXX_EOL);
215
0
  output.append(LOG4CXX_STR("<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\" bordercolor=\"#224466\" width=\"100%\">"));
216
0
  output.append(LOG4CXX_EOL);
217
0
  output.append(LOG4CXX_STR("<tr>"));
218
0
  output.append(LOG4CXX_EOL);
219
0
  output.append(LOG4CXX_STR("<th>Time</th>"));
220
0
  output.append(LOG4CXX_EOL);
221
0
  output.append(LOG4CXX_STR("<th>Thread</th>"));
222
0
  output.append(LOG4CXX_EOL);
223
0
  output.append(LOG4CXX_STR("<th>Level</th>"));
224
0
  output.append(LOG4CXX_EOL);
225
0
  output.append(LOG4CXX_STR("<th>Logger</th>"));
226
0
  output.append(LOG4CXX_EOL);
227
228
0
  if (m_priv->locationInfo)
229
0
  {
230
0
    output.append(LOG4CXX_STR("<th>File:Line</th>"));
231
0
    output.append(LOG4CXX_EOL);
232
0
  }
233
234
0
  output.append(LOG4CXX_STR("<th>Message</th>"));
235
0
  output.append(LOG4CXX_EOL);
236
0
  output.append(LOG4CXX_STR("</tr>"));
237
0
  output.append(LOG4CXX_EOL);
238
0
}
239
240
void HTMLLayout::appendFooter(LogString& output, Pool& /* pool */ )
241
0
{
242
0
  output.append(LOG4CXX_STR("</table>"));
243
0
  output.append(LOG4CXX_EOL);
244
0
  output.append(LOG4CXX_STR("<br>"));
245
0
  output.append(LOG4CXX_EOL);
246
0
  output.append(LOG4CXX_STR("</body></html>"));
247
0
}
248
249
void HTMLLayout::setLocationInfo(bool locationInfoFlag)
250
0
{
251
0
  m_priv->locationInfo = locationInfoFlag;
252
0
}
253
254
bool HTMLLayout::getLocationInfo() const
255
0
{
256
0
  return m_priv->locationInfo;
257
0
}
258
259
void HTMLLayout::setTitle(const LogString& title1)
260
0
{
261
0
  m_priv->title.assign(title1);
262
0
}
263
264
const LogString& HTMLLayout::getTitle() const
265
0
{
266
0
  return m_priv->title;
267
0
}
268
269
LogString HTMLLayout::getContentType() const
270
0
{
271
0
  return LOG4CXX_STR("text/html");
272
0
}
273
274
bool HTMLLayout::ignoresThrowable() const
275
0
{
276
0
  return false;
277
0
}