GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/logging.cc
Date: 2026-02-01 02:35:56
Exec Total Coverage
Lines: 233 343 67.9%
Branches: 157 303 51.8%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * LogCvmfs() handles all message output. It works like printf.
5 * It can log to a debug log file, stdout, stderr, and syslog.
6 * The tracer is a separate module, messages do not overlap with logging.
7 *
8 * The syslog setter routines are not thread-safe. They are meant to be
9 * invoked at the very first, single-threaded stage.
10 *
11 * If DEBUGMSG is undefined, pure debug messages are compiled into no-ops.
12 */
13
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <pthread.h>
17 #include <sys/syslog.h>
18 #include <stdio.h>
19 #include <stdio.h>
20 #include <syslog.h>
21 #include <time.h>
22 #include <unistd.h>
23
24 #include <cassert>
25 #include <cstdarg>
26 #include <cstdio>
27 #include <cstdlib>
28 #include <cstring>
29 #include <ctime>
30 #include <string>
31 #include <vector>
32
33 #include "util/export.h"
34 #include "util/logging_internal.h" // NOLINT(build/include)
35 #include "util/mutex.h"
36 #include "util/platform.h"
37 #include "util/posix.h"
38 #include "util/single_copy.h"
39 #include "util/smalloc.h"
40
41 using namespace std; // NOLINT
42
43 #ifdef CVMFS_NAMESPACE_GUARD
44 namespace CVMFS_NAMESPACE_GUARD {
45 #endif
46
47 static void LogCustom(unsigned id, const std::string &message);
48
49 LogFacilities DefaultLogging::info = kLogSyslog;
50 LogFacilities DefaultLogging::error = kLogSyslogErr;
51
52 void DefaultLogging::Set(LogFacilities info, LogFacilities error) {
53 DefaultLogging::info = info;
54 DefaultLogging::error = error;
55 }
56
57 namespace {
58
59 unsigned gMicroSyslogMax = 500 * 1024; // default: rotate after 500kB
60
61 pthread_mutex_t lock_stdout = PTHREAD_MUTEX_INITIALIZER;
62 pthread_mutex_t lock_stderr = PTHREAD_MUTEX_INITIALIZER;
63 #ifdef DEBUGMSG
64 pthread_mutex_t lock_debug = PTHREAD_MUTEX_INITIALIZER;
65 FILE *file_debug = NULL;
66 string *path_debug = NULL;
67 #endif
68 const char *module_names[] = {
69 "unknown", "cache", "catalog", "sql",
70 "cvmfs", "hash", "download", "compress",
71 "quota", "talk", "monitor", "lru",
72 "fuse stub", "signature", "fs traversal", "catalog traversal",
73 "nfs maps", "publish", "spooler", "concurrency",
74 "utility", "glue buffer", "history", "unionfs",
75 "pathspec", "receiver", "upload s3", "upload http",
76 "s3fanout", "gc", "dns", "authz",
77 "reflog", "kvstore", "telemetry", "curl"};
78 int syslog_facility = LOG_USER;
79 int syslog_level = LOG_NOTICE;
80 char *syslog_prefix = NULL;
81
82 string *usyslog_dest = NULL;
83 int usyslog_fd = -1;
84 int usyslog_fd1 = -1;
85 unsigned usyslog_size = 0;
86 pthread_mutex_t lock_usyslock = PTHREAD_MUTEX_INITIALIZER;
87
88 const unsigned kMaxCustomlog = 3;
89 string *customlog_dests[] = {NULL, NULL, NULL};
90 int customlog_fds[] = {-1, -1, -1};
91 pthread_mutex_t customlog_locks[] = {PTHREAD_MUTEX_INITIALIZER,
92 PTHREAD_MUTEX_INITIALIZER,
93 PTHREAD_MUTEX_INITIALIZER};
94
95 LogLevels max_log_level = kLogNormal;
96 static void (*alt_log_func)(const LogSource source, const int mask,
97 const char *msg) = NULL;
98
99 /**
100 * Circular buffer of the last $n$ calls to LogCvmfs(). Thread-safe class.
101 */
102 class LogBuffer : SingleCopy {
103 public:
104 51 LogBuffer() : next_id_(0) {
105 51 const int retval = pthread_mutex_init(&lock_, NULL);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 assert(retval == 0);
107 51 }
108
109 57 ~LogBuffer() { pthread_mutex_destroy(&lock_); }
110
111 39208996 void Append(const LogBufferEntry &entry) {
112 39208996 const MutexLockGuard lock_guard(lock_);
113 39209140 const size_t idx = next_id_++ % kBufferSize;
114
2/2
✓ Branch 1 taken 957 times.
✓ Branch 2 taken 39208183 times.
39209140 if (idx >= buffer_.size()) {
115
1/2
✓ Branch 1 taken 957 times.
✗ Branch 2 not taken.
957 buffer_.push_back(entry);
116 } else {
117
1/2
✓ Branch 2 taken 39208183 times.
✗ Branch 3 not taken.
39208183 buffer_[idx] = entry;
118 }
119 39209140 }
120
121 208 std::vector<LogBufferEntry> GetBuffer() {
122 // Return a buffer sorted from newest to oldest buffer
123 208 std::vector<LogBufferEntry> sorted_buffer;
124 208 const MutexLockGuard lock_guard(lock_);
125
2/2
✓ Branch 1 taken 1007 times.
✓ Branch 2 taken 208 times.
1215 for (unsigned i = 1; i <= buffer_.size(); ++i) {
126 1007 const unsigned idx = (next_id_ - i) % kBufferSize;
127
1/2
✓ Branch 2 taken 1007 times.
✗ Branch 3 not taken.
1007 sorted_buffer.push_back(buffer_[idx]);
128 }
129 416 return sorted_buffer;
130 208 }
131
132 37 void Clear() {
133 37 const MutexLockGuard lock_guard(lock_);
134 37 next_id_ = 0;
135 37 buffer_.clear();
136 37 }
137
138 private:
139 static const unsigned kBufferSize = 10;
140 pthread_mutex_t lock_;
141 int next_id_;
142 std::vector<LogBufferEntry> buffer_;
143 };
144
145 LogBuffer g_log_buffer;
146
147 } // namespace
148
149 /**
150 * Sets the level that is used for all messages to the syslog facility.
151 */
152 12 void SetLogSyslogLevel(const int level) {
153
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 switch (level) {
154 case 1:
155 syslog_level = LOG_DEBUG;
156 break;
157 case 2:
158 syslog_level = LOG_INFO;
159 break;
160 12 case 3:
161 12 syslog_level = LOG_NOTICE;
162 12 break;
163 default:
164 syslog_level = LOG_NOTICE;
165 break;
166 }
167 12 }
168
169 31 int GetLogSyslogLevel() {
170
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 switch (syslog_level) {
171 case LOG_DEBUG:
172 return 1;
173 case LOG_INFO:
174 return 2;
175 31 default:
176 31 return 3;
177 }
178 }
179
180 /**
181 * Sets the syslog facility to one of local0 .. local7.
182 * Falls back to LOG_USER if local_facility is not in [0..7]
183 */
184 void SetLogSyslogFacility(const int local_facility) {
185 switch (local_facility) {
186 case 0:
187 syslog_facility = LOG_LOCAL0;
188 break;
189 case 1:
190 syslog_facility = LOG_LOCAL1;
191 break;
192 case 2:
193 syslog_facility = LOG_LOCAL2;
194 break;
195 case 3:
196 syslog_facility = LOG_LOCAL3;
197 break;
198 case 4:
199 syslog_facility = LOG_LOCAL4;
200 break;
201 case 5:
202 syslog_facility = LOG_LOCAL5;
203 break;
204 case 6:
205 syslog_facility = LOG_LOCAL6;
206 break;
207 case 7:
208 syslog_facility = LOG_LOCAL7;
209 break;
210 default:
211 syslog_facility = LOG_USER;
212 }
213 }
214
215 31 int GetLogSyslogFacility() {
216
1/9
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 31 times.
31 switch (syslog_facility) {
217 case LOG_LOCAL0:
218 return 0;
219 case LOG_LOCAL1:
220 return 1;
221 case LOG_LOCAL2:
222 return 2;
223 case LOG_LOCAL3:
224 return 3;
225 case LOG_LOCAL4:
226 return 4;
227 case LOG_LOCAL5:
228 return 5;
229 case LOG_LOCAL6:
230 return 6;
231 case LOG_LOCAL7:
232 return 7;
233 31 default:
234 31 return -1;
235 }
236 }
237
238 /**
239 * The syslog prefix is used to distinguish multiple repositories in
240 * /var/log/messages
241 */
242 3003 void SetLogSyslogPrefix(const std::string &prefix) {
243
2/2
✓ Branch 0 taken 1527 times.
✓ Branch 1 taken 1476 times.
3003 if (syslog_prefix)
244 1527 free(syslog_prefix);
245
246
2/2
✓ Branch 1 taken 1466 times.
✓ Branch 2 taken 1537 times.
3003 if (prefix == "") {
247 1466 syslog_prefix = NULL;
248 } else {
249 1537 const unsigned len = prefix.length() + 1;
250 1537 syslog_prefix = static_cast<char *>(smalloc(len));
251 1537 syslog_prefix[len - 1] = '\0';
252 1537 memcpy(syslog_prefix, &prefix[0], prefix.length());
253 }
254 3003 }
255
256 void SetLogSyslogShowPID(bool flag) {
257 openlog(NULL, flag ? LOG_PID : 0, GetLogSyslogFacility());
258 }
259
260 /**
261 * Set the maximum verbosity level. By default kLogNormal.
262 */
263 58 void SetLogVerbosity(const LogLevels max_level) { max_log_level = max_level; }
264
265
266 37 void SetLogMicroSyslogMaxSize(unsigned bytes) { gMicroSyslogMax = bytes; }
267
268 /**
269 * "Micro-Syslog" write kLogSyslog messages into filename. It rotates this
270 * file. Requires for µCernVM
271 */
272 1844 void SetLogMicroSyslog(const std::string &filename) {
273 1844 pthread_mutex_lock(&lock_usyslock);
274
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 1771 times.
1844 if (usyslog_fd >= 0) {
275
1/2
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
73 close(usyslog_fd);
276
1/2
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
73 close(usyslog_fd1);
277 73 usyslog_fd = -1;
278 73 usyslog_fd1 = -1;
279 }
280
281
2/2
✓ Branch 1 taken 1771 times.
✓ Branch 2 taken 73 times.
1844 if (filename == "") {
282
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 1698 times.
1771 delete usyslog_dest;
283 1771 usyslog_dest = NULL;
284 1771 pthread_mutex_unlock(&lock_usyslock);
285 1771 return;
286 }
287
288
1/2
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
73 usyslog_fd = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (usyslog_fd < 0) {
290 fprintf(stderr, "could not open usyslog file %s (%d), aborting\n",
291 filename.c_str(), errno);
292 abort();
293 }
294
2/4
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 73 times.
✗ Branch 6 not taken.
73 usyslog_fd1 = open((filename + ".1").c_str(), O_WRONLY | O_CREAT, 0600);
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (usyslog_fd1 < 0) {
296 fprintf(stderr, "could not open usyslog.1 file %s.1 (%d), aborting\n",
297 filename.c_str(), errno);
298 abort();
299 }
300 platform_stat64 info;
301 73 const int retval = platform_fstat(usyslog_fd, &info);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 assert(retval == 0);
303 73 usyslog_size = info.st_size;
304
2/4
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
73 usyslog_dest = new string(filename);
305 73 pthread_mutex_unlock(&lock_usyslock);
306 }
307
308 76 std::string GetLogMicroSyslog() {
309 76 pthread_mutex_lock(&lock_usyslock);
310 76 string result;
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (usyslog_dest)
312 result = *usyslog_dest;
313 76 pthread_mutex_unlock(&lock_usyslock);
314 76 return result;
315 }
316
317 37144 static void LogMicroSyslog(const std::string &message) {
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37144 times.
37144 if (message.size() == 0)
319 return;
320
321 37144 pthread_mutex_lock(&lock_usyslock);
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37144 times.
37144 if (usyslog_fd < 0) {
323 pthread_mutex_unlock(&lock_usyslock);
324 return;
325 }
326
327 37144 const int written = write(usyslog_fd, message.data(), message.size());
328
3/6
✓ Branch 0 taken 37144 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 37144 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 37144 times.
37144 if ((written < 0) || (static_cast<unsigned>(written) != message.size())) {
329 close(usyslog_fd);
330 usyslog_fd = -1;
331 abort();
332 }
333 37144 int retval = fsync(usyslog_fd);
334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37144 times.
37144 assert(retval == 0);
335 37144 usyslog_size += written;
336
337
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 36885 times.
37144 if (usyslog_size >= gMicroSyslogMax) {
338 // Wipe out usyslog.1 file
339 259 retval = ftruncate(usyslog_fd1, 0);
340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 assert(retval == 0);
341
342 // Copy from usyslog to usyslog.1
343 259 retval = lseek(usyslog_fd, 0, SEEK_SET);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 assert(retval == 0);
345 unsigned char buf[4096];
346 int num_bytes;
347 do {
348
1/2
✓ Branch 1 taken 259 times.
✗ Branch 2 not taken.
259 num_bytes = read(usyslog_fd, buf, 4096);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 assert(num_bytes >= 0);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 if (num_bytes == 0)
351 break;
352
1/2
✓ Branch 1 taken 259 times.
✗ Branch 2 not taken.
259 const int written = write(usyslog_fd1, buf, num_bytes);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 assert(written == num_bytes);
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 } while (num_bytes == 4096);
355 259 retval = lseek(usyslog_fd1, 0, SEEK_SET);
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 assert(retval == 0);
357
358 // Reset usyslog
359 259 retval = lseek(usyslog_fd, 0, SEEK_SET);
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 assert(retval == 0);
361 259 retval = ftruncate(usyslog_fd, 0);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 259 times.
259 assert(retval == 0);
363 259 usyslog_size = 0;
364 }
365 37144 pthread_mutex_unlock(&lock_usyslock);
366 }
367
368 /**
369 * Changes the debug log file from stderr. No effect if DEBUGMSG is undefined.
370 */
371 #ifdef DEBUGMSG
372 1564 void SetLogDebugFile(const string &filename) {
373
1/2
✓ Branch 1 taken 1564 times.
✗ Branch 2 not taken.
1564 if (filename == "") {
374
2/4
✓ Branch 0 taken 1564 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1564 times.
1564 if ((file_debug != NULL) && (file_debug != stderr)) {
375 fclose(file_debug);
376 file_debug = NULL;
377 }
378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1564 times.
1564 delete path_debug;
379 1564 path_debug = NULL;
380 1564 return;
381 }
382
383 if ((file_debug != NULL) && (file_debug != stderr)) {
384 if ((fclose(file_debug) < 0)) {
385 fprintf(stderr, "could not close current log file (%d), aborting\n",
386 errno);
387
388 abort();
389 }
390 }
391 const int fd = open(filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0600);
392 if ((fd < 0) || ((file_debug = fdopen(fd, "a")) == NULL)) {
393 fprintf(stderr, "could not open debug log file %s (%d), aborting\n",
394 filename.c_str(), errno);
395 syslog(syslog_facility | LOG_ERR,
396 "could not open debug log file %s (%d), "
397 "aborting\n",
398 filename.c_str(), errno);
399 abort();
400 }
401 delete path_debug;
402 path_debug = new string(filename);
403 }
404
405 80 string GetLogDebugFile() {
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (path_debug)
407 return *path_debug;
408
1/2
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 return "";
409 }
410 #endif
411
412 155 void SetAltLogFunc(void (*fn)(const LogSource source, const int mask,
413 const char *msg)) {
414 155 alt_log_func = fn;
415 155 }
416
417
418 /**
419 * Logs a message to one or multiple facilities specified by mask.
420 * Mask can be extended by a log level in the future, using the higher bits.
421 *
422 * @param[in] source Component that triggers the logging
423 * @param[in] mask Bit mask of log facilities
424 * @param[in] format Format string followed by arguments like printf
425 */
426 CVMFS_EXPORT
427 39217216 void vLogCvmfs(const LogSource source, const int mask, const char *format,
428 va_list variadic_list) {
429 39217216 char *msg = NULL;
430
431 // Log level check, no flag set in mask means kLogNormal
432 #ifndef DEBUGMSG
433 int log_level = mask & ((2 * kLogNone - 1) ^ (kLogLevel0 - 1));
434 if (!log_level)
435 log_level = kLogNormal;
436 if (log_level == kLogNone)
437 return;
438 if (log_level > max_log_level)
439 return;
440 #endif
441
442 // Format the message string
443 39217216 const int retval = vasprintf(&msg, format, variadic_list);
444
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 39217390 times.
39217546 assert(retval != -1); // else: out of memory
445
446
2/2
✓ Branch 0 taken 8369 times.
✓ Branch 1 taken 39209021 times.
39217390 if (alt_log_func) {
447
1/2
✓ Branch 1 taken 8369 times.
✗ Branch 2 not taken.
8369 (*alt_log_func)(source, mask, msg);
448 8369 return;
449 }
450
451 #ifdef DEBUGMSG
452
2/2
✓ Branch 0 taken 25286240 times.
✓ Branch 1 taken 13922781 times.
39209021 if (mask & kLogDebug) {
453 25286240 pthread_mutex_lock(&lock_debug);
454
455 // Set the file pointer for debugging to stderr, if necessary
456
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 25286142 times.
25286240 if (file_debug == NULL)
457 98 file_debug = stderr;
458
459 // Get timestamp
460 time_t rawtime;
461 25286240 time(&rawtime);
462 struct tm now;
463 25286240 localtime_r(&rawtime, &now);
464
465
1/2
✓ Branch 0 taken 25286240 times.
✗ Branch 1 not taken.
25286240 if (file_debug == stderr)
466 25286240 pthread_mutex_lock(&lock_stderr);
467 25286240 fprintf(file_debug, "(%s) %s [%02d-%02d-%04d %02d:%02d:%02d %s]\n",
468 25286240 module_names[source], msg, (now.tm_mon) + 1, now.tm_mday,
469
1/2
✓ Branch 1 taken 25286240 times.
✗ Branch 2 not taken.
25286240 (now.tm_year) + 1900, now.tm_hour, now.tm_min, now.tm_sec,
470 now.tm_zone);
471
1/2
✓ Branch 1 taken 25286240 times.
✗ Branch 2 not taken.
25286240 fflush(file_debug);
472
1/2
✓ Branch 0 taken 25286240 times.
✗ Branch 1 not taken.
25286240 if (file_debug == stderr)
473 25286240 pthread_mutex_unlock(&lock_stderr);
474
475 25286240 pthread_mutex_unlock(&lock_debug);
476 }
477 #endif
478
479
2/2
✓ Branch 0 taken 13702085 times.
✓ Branch 1 taken 25506936 times.
39209021 if (mask & kLogStdout) {
480 13702085 pthread_mutex_lock(&lock_stdout);
481
2/2
✓ Branch 0 taken 13694565 times.
✓ Branch 1 taken 7715 times.
13702280 if (mask & kLogShowSource)
482
1/2
✓ Branch 1 taken 13694565 times.
✗ Branch 2 not taken.
13694565 printf("(%s) ", module_names[source]);
483
1/2
✓ Branch 1 taken 13702280 times.
✗ Branch 2 not taken.
13702280 printf("%s", msg);
484
2/2
✓ Branch 0 taken 13701934 times.
✓ Branch 1 taken 346 times.
13702280 if (!(mask & kLogNoLinebreak))
485
1/2
✓ Branch 1 taken 13701934 times.
✗ Branch 2 not taken.
13701934 printf("\n");
486
1/2
✓ Branch 1 taken 13702280 times.
✗ Branch 2 not taken.
13702280 fflush(stdout);
487 13702280 pthread_mutex_unlock(&lock_stdout);
488 }
489
490
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 39208973 times.
39209216 if (mask & kLogStderr) {
491 243 pthread_mutex_lock(&lock_stderr);
492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
243 if (mask & kLogShowSource)
493 fprintf(stderr, "(%s) ", module_names[source]);
494
1/2
✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
243 fprintf(stderr, "%s", msg);
495
1/2
✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
243 if (!(mask & kLogNoLinebreak))
496
1/2
✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
243 fprintf(stderr, "\n");
497
1/2
✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
243 fflush(stderr);
498 243 pthread_mutex_unlock(&lock_stderr);
499 }
500
501
2/2
✓ Branch 0 taken 46207 times.
✓ Branch 1 taken 39163009 times.
39209216 if (mask & (kLogSyslog | kLogSyslogWarn | kLogSyslogErr)) {
502
2/2
✓ Branch 0 taken 37144 times.
✓ Branch 1 taken 9063 times.
46207 if (usyslog_dest) {
503
1/2
✓ Branch 2 taken 37144 times.
✗ Branch 3 not taken.
37144 string fmt_msg(msg);
504
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 37036 times.
37144 if (syslog_prefix)
505
4/8
✓ Branch 2 taken 108 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 108 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 108 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 108 times.
✗ Branch 12 not taken.
108 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
506 time_t rawtime;
507 37144 time(&rawtime);
508 char fmt_time[26];
509 37144 ctime_r(&rawtime, fmt_time);
510
3/6
✓ Branch 2 taken 37144 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 37144 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 37144 times.
✗ Branch 9 not taken.
37144 fmt_msg = string(fmt_time, 24) + " " + fmt_msg;
511
1/2
✓ Branch 1 taken 37144 times.
✗ Branch 2 not taken.
37144 fmt_msg.push_back('\n');
512
1/2
✓ Branch 1 taken 37144 times.
✗ Branch 2 not taken.
37144 LogMicroSyslog(fmt_msg);
513 37144 } else {
514 9063 int level = syslog_level;
515
2/2
✓ Branch 0 taken 3622 times.
✓ Branch 1 taken 5441 times.
9063 if (mask & kLogSyslogWarn)
516 3622 level = LOG_WARNING;
517
2/2
✓ Branch 0 taken 1194 times.
✓ Branch 1 taken 7869 times.
9063 if (mask & kLogSyslogErr)
518 1194 level = LOG_ERR;
519
2/2
✓ Branch 0 taken 3072 times.
✓ Branch 1 taken 5991 times.
9063 if (syslog_prefix) {
520
1/2
✓ Branch 1 taken 3072 times.
✗ Branch 2 not taken.
3072 syslog(syslog_facility | level, "(%s) %s", syslog_prefix, msg);
521 } else {
522
1/2
✓ Branch 1 taken 5913 times.
✗ Branch 2 not taken.
5991 syslog(syslog_facility | level, "%s", msg);
523 }
524 }
525 }
526
527
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 39209014 times.
39209138 if (mask & (kLogCustom0 | kLogCustom1 | kLogCustom2)) {
528
1/2
✓ Branch 2 taken 124 times.
✗ Branch 3 not taken.
124 string fmt_msg(msg);
529
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 if (syslog_prefix)
530
4/8
✓ Branch 2 taken 124 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 124 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 124 times.
✗ Branch 12 not taken.
124 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
531
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 if (!(mask & kLogNoLinebreak))
532
1/2
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
124 fmt_msg += "\n";
533
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 62 times.
124 if (mask & kLogCustom0)
534
1/2
✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
62 LogCustom(0, fmt_msg);
535
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 93 times.
124 if (mask & kLogCustom1)
536
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 LogCustom(1, fmt_msg);
537
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 93 times.
124 if (mask & kLogCustom2)
538
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 LogCustom(2, fmt_msg);
539 124 }
540
541 // The log buffer can be read via extended attributes from cvmfs, therefore
542 // we provide an option to hide entries from the buffer if they contain
543 // sensitive information
544
2/2
✓ Branch 0 taken 39209101 times.
✓ Branch 1 taken 37 times.
39209138 if (!(mask & kLogSensitive))
545
3/6
✓ Branch 2 taken 39209074 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 39209074 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 39209140 times.
✗ Branch 9 not taken.
39209101 g_log_buffer.Append(LogBufferEntry(source, mask, msg));
546
547 39209177 free(msg);
548 }
549 CVMFS_EXPORT
550 39217099 void LogCvmfs(const LogSource source, const int mask, const char *format, ...) {
551 va_list variadic_list;
552 39217099 va_start(variadic_list, format);
553
1/2
✓ Branch 1 taken 39217546 times.
✗ Branch 2 not taken.
39217099 vLogCvmfs(source, mask, format, variadic_list);
554 39217546 va_end(variadic_list);
555 39217546 }
556
557 208 std::vector<LogBufferEntry> GetLogBuffer() { return g_log_buffer.GetBuffer(); }
558
559 37 void ClearLogBuffer() { g_log_buffer.Clear(); }
560
561 5 void PrintError(const string &message) {
562 5 LogCvmfs(kLogCvmfs, kLogStderr, "[ERROR] %s", message.c_str());
563 5 }
564
565 void PrintWarning(const string &message) {
566 LogCvmfs(kLogCvmfs, kLogStderr, "[WARNING] %s", message.c_str());
567 }
568
569
570 /**
571 * Opens a custom log file
572 */
573 609 void SetLogCustomFile(unsigned id, const std::string &filename) {
574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 609 times.
609 assert(id < kMaxCustomlog);
575 609 pthread_mutex_lock(&customlog_locks[id]);
576
577
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 516 times.
609 if (customlog_fds[id] >= 0) {
578 93 close(customlog_fds[id]);
579 93 customlog_fds[id] = -1;
580 }
581
582
2/2
✓ Branch 1 taken 513 times.
✓ Branch 2 taken 96 times.
609 if (filename.empty()) {
583
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 420 times.
513 delete customlog_dests[id];
584 513 customlog_dests[id] = NULL;
585 513 pthread_mutex_unlock(&customlog_locks[id]);
586 513 return;
587 }
588
589 96 customlog_fds[id] = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (customlog_fds[id] < 0) {
591 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
592 "could not open log file %s (%d), aborting", filename.c_str(),
593 errno);
594 abort();
595 }
596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 delete customlog_dests[id];
597
1/2
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
96 customlog_dests[id] = new string(filename);
598
599 96 pthread_mutex_unlock(&customlog_locks[id]);
600 }
601
602
603 124 static void LogCustom(unsigned id, const std::string &message) {
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
124 assert(id < kMaxCustomlog);
605
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 124 times.
124 if (message.size() == 0)
606 return;
607
608 124 pthread_mutex_lock(&customlog_locks[id]);
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
124 assert(customlog_fds[id] >= 0);
610
611 124 const bool retval_b = SafeWrite(customlog_fds[id], message.data(),
612 message.size());
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
124 if (!retval_b) {
614 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
615 "could not write into log file %s (%d), aborting - lost: %s",
616 customlog_dests[id]->c_str(), errno, message.c_str());
617 abort();
618 }
619 124 const int retval_i = fsync(customlog_fds[id]);
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
124 assert(retval_i == 0);
621
622 124 pthread_mutex_unlock(&customlog_locks[id]);
623 }
624
625
626 171 void LogShutdown() {
627
2/4
✓ Branch 2 taken 171 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 171 times.
✗ Branch 6 not taken.
171 SetLogMicroSyslog("");
628
2/2
✓ Branch 0 taken 513 times.
✓ Branch 1 taken 171 times.
684 for (unsigned i = 0; i < kMaxCustomlog; ++i)
629
2/4
✓ Branch 2 taken 513 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 513 times.
✗ Branch 6 not taken.
513 SetLogCustomFile(i, "");
630 171 }
631
632
633 #ifdef CVMFS_NAMESPACE_GUARD
634 } // namespace CVMFS_NAMESPACE_GUARD
635 #endif
636