Coverage Report

Created: 2025-07-11 07:00

/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
2.98k
    : locationInfo(false)
37
2.98k
    , title(LOG4CXX_STR("Log4cxx Log Messages"))
38
2.98k
    , dateFormat()
39
2.98k
    , expectedPatternLength(100)
40
2.98k
    {}
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
2.98k
  : m_priv(std::make_unique<HTMLLayoutPrivate>())
58
2.98k
{
59
2.98k
  m_priv->dateFormat.setTimeZone(TimeZone::getGMT());
60
2.98k
  m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
61
2.98k
}
Unexecuted instantiation: log4cxx::HTMLLayout::HTMLLayout()
log4cxx::HTMLLayout::HTMLLayout()
Line
Count
Source
57
2.98k
  : m_priv(std::make_unique<HTMLLayoutPrivate>())
58
2.98k
{
59
2.98k
  m_priv->dateFormat.setTimeZone(TimeZone::getGMT());
60
2.98k
  m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
61
2.98k
}
62
63
2.98k
HTMLLayout::~HTMLLayout() {}
64
65
66
void HTMLLayout::setOption(const LogString& option,
67
  const LogString& value)
68
2.75k
{
69
70
2.75k
  if (StringHelper::equalsIgnoreCase(option,
71
2.75k
      LOG4CXX_STR("TITLE"), LOG4CXX_STR("title")))
72
1.04k
  {
73
1.04k
    setTitle(value);
74
1.04k
  }
75
1.71k
  else if (StringHelper::equalsIgnoreCase(option,
76
1.71k
      LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
77
1.71k
  {
78
1.71k
    setLocationInfo(OptionConverter::toBoolean(value, false));
79
1.71k
    m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
80
1.71k
  }
81
2.75k
}
82
83
void HTMLLayout::format(LogString& output,
84
  const spi::LoggingEventPtr& event,
85
  Pool& p) const
86
7.67k
{
87
7.67k
  output.reserve(m_priv->expectedPatternLength + event->getMessage().size());
88
7.67k
  output.append(LOG4CXX_EOL);
89
7.67k
  output.append(LOG4CXX_STR("<tr>"));
90
7.67k
  output.append(LOG4CXX_EOL);
91
7.67k
  output.append(LOG4CXX_STR("<td>"));
92
93
7.67k
  m_priv->dateFormat.format(output, event->getTimeStamp(), p);
94
95
96
7.67k
  output.append(LOG4CXX_STR("</td>"));
97
7.67k
  output.append(LOG4CXX_EOL);
98
99
7.67k
  output.append(LOG4CXX_STR("<td title=\""));
100
7.67k
  LogString threadName(event->getThreadName());
101
7.67k
  output.append(threadName);
102
7.67k
  output.append(LOG4CXX_STR(" thread\">"));
103
7.67k
  output.append(threadName);
104
7.67k
  output.append(LOG4CXX_STR("</td>"));
105
7.67k
  output.append(LOG4CXX_EOL);
106
107
7.67k
  output.append(LOG4CXX_STR("<td title=\"Level\">"));
108
109
7.67k
  if (event->getLevel()->equals(Level::getDebug()))
110
4.69k
  {
111
4.69k
    output.append(LOG4CXX_STR("<font color=\"#339933\">"));
112
4.69k
    output.append(event->getLevel()->toString());
113
4.69k
    output.append(LOG4CXX_STR("</font>"));
114
4.69k
  }
115
2.98k
  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
2.98k
  else
122
2.98k
  {
123
2.98k
    output.append(event->getLevel()->toString());
124
2.98k
  }
125
126
7.67k
  output.append(LOG4CXX_STR("</td>"));
127
7.67k
  output.append(LOG4CXX_EOL);
128
129
7.67k
  output.append(LOG4CXX_STR("<td title=\""));
130
7.67k
  output.append(event->getLoggerName());
131
7.67k
  output.append(LOG4CXX_STR(" logger\">"));
132
7.67k
  Transform::appendEscapingTags(output, event->getLoggerName());
133
7.67k
  output.append(LOG4CXX_STR("</td>"));
134
7.67k
  output.append(LOG4CXX_EOL);
135
136
7.67k
  if (m_priv->locationInfo)
137
3.42k
  {
138
3.42k
    output.append(LOG4CXX_STR("<td>"));
139
3.42k
    const LocationInfo& locInfo = event->getLocationInformation();
140
3.42k
    LOG4CXX_DECODE_CHAR(fileName, locInfo.getFileName());
141
3.42k
    Transform::appendEscapingTags(output, fileName);
142
3.42k
    output.append(1, (logchar) 0x3A /* ':' */);
143
3.42k
    int line = event->getLocationInformation().getLineNumber();
144
145
3.42k
    if (line != 0)
146
3.42k
    {
147
3.42k
      StringHelper::toString(line, p, output);
148
3.42k
    }
149
150
3.42k
    output.append(LOG4CXX_STR("</td>"));
151
3.42k
    output.append(LOG4CXX_EOL);
152
3.42k
  }
153
154
7.67k
  output.append(LOG4CXX_STR("<td title=\"Message\">"));
155
7.67k
  Transform::appendEscapingTags(output, event->getRenderedMessage());
156
7.67k
  output.append(LOG4CXX_STR("</td>"));
157
7.67k
  output.append(LOG4CXX_EOL);
158
7.67k
  output.append(LOG4CXX_STR("</tr>"));
159
7.67k
  output.append(LOG4CXX_EOL);
160
161
7.67k
  LogString ndcVal;
162
163
7.67k
  if (event->getNDC(ndcVal))
164
2.98k
  {
165
2.98k
    output.append(LOG4CXX_STR("<tr><td bgcolor=\"#EEEEEE\" "));
166
2.98k
    output.append(LOG4CXX_STR("style=\"font-size : xx-small;\" colspan=\"6\" "));
167
2.98k
    output.append(LOG4CXX_STR("title=\"Nested Diagnostic Context\">"));
168
2.98k
    output.append(LOG4CXX_STR("NDC: "));
169
2.98k
    Transform::appendEscapingTags(output, ndcVal);
170
2.98k
    output.append(LOG4CXX_STR("</td></tr>"));
171
2.98k
    output.append(LOG4CXX_EOL);
172
2.98k
  }
173
7.67k
}
174
175
void HTMLLayout::appendHeader(LogString& output, Pool& p)
176
1.06k
{
177
1.06k
  output.append(LOG4CXX_STR("<!DOCTYPE HTML PUBLIC "));
178
1.06k
  output.append(LOG4CXX_STR("\"-//W3C//DTD HTML 4.01 Transitional//EN\" "));
179
1.06k
  output.append(LOG4CXX_STR("\"http://www.w3.org/TR/html4/loose.dtd\">"));
180
1.06k
  output.append(LOG4CXX_EOL);
181
1.06k
  output.append(LOG4CXX_STR("<html>"));
182
1.06k
  output.append(LOG4CXX_EOL);
183
1.06k
  output.append(LOG4CXX_STR("<head>"));
184
1.06k
  output.append(LOG4CXX_EOL);
185
1.06k
  output.append(LOG4CXX_STR("<title>"));
186
1.06k
  output.append(m_priv->title);
187
1.06k
  output.append(LOG4CXX_STR("</title>"));
188
1.06k
  output.append(LOG4CXX_EOL);
189
1.06k
  output.append(LOG4CXX_STR("<style type=\"text/css\">"));
190
1.06k
  output.append(LOG4CXX_EOL);
191
1.06k
  output.append(LOG4CXX_STR("<!--"));
192
1.06k
  output.append(LOG4CXX_EOL);
193
1.06k
  output.append(LOG4CXX_STR("body, table {font-family: arial,sans-serif; font-size: x-small;}"));
194
1.06k
  output.append(LOG4CXX_EOL);
195
1.06k
  output.append(LOG4CXX_STR("th {background: #336699; color: #FFFFFF; text-align: left;}"));
196
1.06k
  output.append(LOG4CXX_EOL);
197
1.06k
  output.append(LOG4CXX_STR("-->"));
198
1.06k
  output.append(LOG4CXX_EOL);
199
1.06k
  output.append(LOG4CXX_STR("</style>"));
200
1.06k
  output.append(LOG4CXX_EOL);
201
1.06k
  output.append(LOG4CXX_STR("</head>"));
202
1.06k
  output.append(LOG4CXX_EOL);
203
1.06k
  output.append(LOG4CXX_STR("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">"));
204
1.06k
  output.append(LOG4CXX_EOL);
205
1.06k
  output.append(LOG4CXX_STR("<hr size=\"1\" noshade>"));
206
1.06k
  output.append(LOG4CXX_EOL);
207
1.06k
  output.append(LOG4CXX_STR("Log session start time "));
208
209
1.06k
  m_priv->dateFormat.format(output, Date::currentTime(), p);
210
211
1.06k
  output.append(LOG4CXX_STR("<br>"));
212
1.06k
  output.append(LOG4CXX_EOL);
213
1.06k
  output.append(LOG4CXX_STR("<br>"));
214
1.06k
  output.append(LOG4CXX_EOL);
215
1.06k
  output.append(LOG4CXX_STR("<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\" bordercolor=\"#224466\" width=\"100%\">"));
216
1.06k
  output.append(LOG4CXX_EOL);
217
1.06k
  output.append(LOG4CXX_STR("<tr>"));
218
1.06k
  output.append(LOG4CXX_EOL);
219
1.06k
  output.append(LOG4CXX_STR("<th>Time</th>"));
220
1.06k
  output.append(LOG4CXX_EOL);
221
1.06k
  output.append(LOG4CXX_STR("<th>Thread</th>"));
222
1.06k
  output.append(LOG4CXX_EOL);
223
1.06k
  output.append(LOG4CXX_STR("<th>Level</th>"));
224
1.06k
  output.append(LOG4CXX_EOL);
225
1.06k
  output.append(LOG4CXX_STR("<th>Logger</th>"));
226
1.06k
  output.append(LOG4CXX_EOL);
227
228
1.06k
  if (m_priv->locationInfo)
229
754
  {
230
754
    output.append(LOG4CXX_STR("<th>File:Line</th>"));
231
754
    output.append(LOG4CXX_EOL);
232
754
  }
233
234
1.06k
  output.append(LOG4CXX_STR("<th>Message</th>"));
235
1.06k
  output.append(LOG4CXX_EOL);
236
1.06k
  output.append(LOG4CXX_STR("</tr>"));
237
1.06k
  output.append(LOG4CXX_EOL);
238
1.06k
}
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
1.71k
{
251
1.71k
  m_priv->locationInfo = locationInfoFlag;
252
1.71k
}
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
1.04k
{
261
1.04k
  m_priv->title.assign(title1);
262
1.04k
}
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
}