GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/logging.cc
Date: 2026-04-05 02:35:23
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 15480730 void Append(const LogBufferEntry &entry) {
112 15480730 const MutexLockGuard lock_guard(lock_);
113 15480757 const size_t idx = next_id_++ % kBufferSize;
114
2/2
✓ Branch 1 taken 727 times.
✓ Branch 2 taken 15480030 times.
15480757 if (idx >= buffer_.size()) {
115
1/2
✓ Branch 1 taken 727 times.
✗ Branch 2 not taken.
727 buffer_.push_back(entry);
116 } else {
117
1/2
✓ Branch 2 taken 15480030 times.
✗ Branch 3 not taken.
15480030 buffer_[idx] = entry;
118 }
119 15480757 }
120
121 96 std::vector<LogBufferEntry> GetBuffer() {
122 // Return a buffer sorted from newest to oldest buffer
123 96 std::vector<LogBufferEntry> sorted_buffer;
124 96 const MutexLockGuard lock_guard(lock_);
125
2/2
✓ Branch 1 taken 554 times.
✓ Branch 2 taken 96 times.
650 for (unsigned i = 1; i <= buffer_.size(); ++i) {
126 554 const unsigned idx = (next_id_ - i) % kBufferSize;
127
1/2
✓ Branch 2 taken 554 times.
✗ Branch 3 not taken.
554 sorted_buffer.push_back(buffer_[idx]);
128 }
129 192 return sorted_buffer;
130 96 }
131
132 14 void Clear() {
133 14 const MutexLockGuard lock_guard(lock_);
134 14 next_id_ = 0;
135 14 buffer_.clear();
136 14 }
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 117 void SetLogSyslogLevel(const int level) {
153
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
✗ Branch 3 not taken.
117 switch (level) {
154 case 1:
155 syslog_level = LOG_DEBUG;
156 break;
157 case 2:
158 syslog_level = LOG_INFO;
159 break;
160 117 case 3:
161 117 syslog_level = LOG_NOTICE;
162 117 break;
163 default:
164 syslog_level = LOG_NOTICE;
165 break;
166 }
167 117 }
168
169 63 int GetLogSyslogLevel() {
170
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
63 switch (syslog_level) {
171 case LOG_DEBUG:
172 return 1;
173 case LOG_INFO:
174 return 2;
175 63 default:
176 63 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 63 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 63 times.
63 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 63 default:
234 63 return -1;
235 }
236 }
237
238 /**
239 * The syslog prefix is used to distinguish multiple repositories in
240 * /var/log/messages
241 */
242 4818 void SetLogSyslogPrefix(const std::string &prefix) {
243
2/2
✓ Branch 0 taken 2420 times.
✓ Branch 1 taken 2398 times.
4818 if (syslog_prefix)
244 2420 free(syslog_prefix);
245
246
2/2
✓ Branch 1 taken 2393 times.
✓ Branch 2 taken 2425 times.
4818 if (prefix == "") {
247 2393 syslog_prefix = NULL;
248 } else {
249 2425 const unsigned len = prefix.length() + 1;
250 2425 syslog_prefix = static_cast<char *>(smalloc(len));
251 2425 syslog_prefix[len - 1] = '\0';
252 2425 memcpy(syslog_prefix, &prefix[0], prefix.length());
253 }
254 4818 }
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 24 void SetLogVerbosity(const LogLevels max_level) { max_log_level = max_level; }
264
265
266 20 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 2613 void SetLogMicroSyslog(const std::string &filename) {
273 2613 pthread_mutex_lock(&lock_usyslock);
274
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2580 times.
2613 if (usyslog_fd >= 0) {
275
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 close(usyslog_fd);
276
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 close(usyslog_fd1);
277 33 usyslog_fd = -1;
278 33 usyslog_fd1 = -1;
279 }
280
281
2/2
✓ Branch 1 taken 2580 times.
✓ Branch 2 taken 33 times.
2613 if (filename == "") {
282
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2547 times.
2580 delete usyslog_dest;
283 2580 usyslog_dest = NULL;
284 2580 pthread_mutex_unlock(&lock_usyslock);
285 2580 return;
286 }
287
288
1/2
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 usyslog_fd = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 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 33 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
33 usyslog_fd1 = open((filename + ".1").c_str(), O_WRONLY | O_CREAT, 0600);
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 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 33 const int retval = platform_fstat(usyslog_fd, &info);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 assert(retval == 0);
303 33 usyslog_size = info.st_size;
304
2/4
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
33 usyslog_dest = new string(filename);
305 33 pthread_mutex_unlock(&lock_usyslock);
306 }
307
308 60 std::string GetLogMicroSyslog() {
309 60 pthread_mutex_lock(&lock_usyslock);
310 60 string result;
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (usyslog_dest)
312 result = *usyslog_dest;
313 60 pthread_mutex_unlock(&lock_usyslock);
314 60 return result;
315 }
316
317 20052 static void LogMicroSyslog(const std::string &message) {
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20052 times.
20052 if (message.size() == 0)
319 return;
320
321 20052 pthread_mutex_lock(&lock_usyslock);
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20052 times.
20052 if (usyslog_fd < 0) {
323 pthread_mutex_unlock(&lock_usyslock);
324 return;
325 }
326
327 20052 const int written = write(usyslog_fd, message.data(), message.size());
328
3/6
✓ Branch 0 taken 20052 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 20052 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20052 times.
20052 if ((written < 0) || (static_cast<unsigned>(written) != message.size())) {
329 close(usyslog_fd);
330 usyslog_fd = -1;
331 abort();
332 }
333 20052 int retval = fsync(usyslog_fd);
334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20052 times.
20052 assert(retval == 0);
335 20052 usyslog_size += written;
336
337
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 19912 times.
20052 if (usyslog_size >= gMicroSyslogMax) {
338 // Wipe out usyslog.1 file
339 140 retval = ftruncate(usyslog_fd1, 0);
340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(retval == 0);
341
342 // Copy from usyslog to usyslog.1
343 140 retval = lseek(usyslog_fd, 0, SEEK_SET);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(retval == 0);
345 unsigned char buf[4096];
346 int num_bytes;
347 do {
348
1/2
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 num_bytes = read(usyslog_fd, buf, 4096);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(num_bytes >= 0);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (num_bytes == 0)
351 break;
352
1/2
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 const int written = write(usyslog_fd1, buf, num_bytes);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(written == num_bytes);
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 } while (num_bytes == 4096);
355 140 retval = lseek(usyslog_fd1, 0, SEEK_SET);
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(retval == 0);
357
358 // Reset usyslog
359 140 retval = lseek(usyslog_fd, 0, SEEK_SET);
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(retval == 0);
361 140 retval = ftruncate(usyslog_fd, 0);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(retval == 0);
363 140 usyslog_size = 0;
364 }
365 20052 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 2491 void SetLogDebugFile(const string &filename) {
373
1/2
✓ Branch 1 taken 2491 times.
✗ Branch 2 not taken.
2491 if (filename == "") {
374
2/4
✓ Branch 0 taken 2491 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2491 times.
2491 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 2491 times.
2491 delete path_debug;
379 2491 path_debug = NULL;
380 2491 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 112 string GetLogDebugFile() {
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (path_debug)
407 return *path_debug;
408
1/2
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
112 return "";
409 }
410 #endif
411
412 401 void SetAltLogFunc(void (*fn)(const LogSource source, const int mask,
413 const char *msg)) {
414 401 alt_log_func = fn;
415 401 }
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 15558161 void vLogCvmfs(const LogSource source, const int mask, const char *format,
428 va_list variadic_list) {
429 15558161 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 15558161 const int retval = vasprintf(&msg, format, variadic_list);
444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15558716 times.
15558630 assert(retval != -1); // else: out of memory
445
446
2/2
✓ Branch 0 taken 78141 times.
✓ Branch 1 taken 15480575 times.
15558716 if (alt_log_func) {
447
1/2
✓ Branch 1 taken 78141 times.
✗ Branch 2 not taken.
78141 (*alt_log_func)(source, mask, msg);
448 78141 return;
449 }
450
451 #ifdef DEBUGMSG
452
2/2
✓ Branch 0 taken 11844285 times.
✓ Branch 1 taken 3636290 times.
15480575 if (mask & kLogDebug) {
453 11844285 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 11844319 times.
11844417 if (file_debug == NULL)
457 98 file_debug = stderr;
458
459 // Get timestamp
460 time_t rawtime;
461 11844417 time(&rawtime);
462 struct tm now;
463 11844417 localtime_r(&rawtime, &now);
464
465
1/2
✓ Branch 0 taken 11844417 times.
✗ Branch 1 not taken.
11844417 if (file_debug == stderr)
466 11844417 pthread_mutex_lock(&lock_stderr);
467 11844417 fprintf(file_debug, "(%s) %s [%02d-%02d-%04d %02d:%02d:%02d %s]\n",
468 11844417 module_names[source], msg, (now.tm_mon) + 1, now.tm_mday,
469
1/2
✓ Branch 1 taken 11844417 times.
✗ Branch 2 not taken.
11844417 (now.tm_year) + 1900, now.tm_hour, now.tm_min, now.tm_sec,
470 now.tm_zone);
471
1/2
✓ Branch 1 taken 11844417 times.
✗ Branch 2 not taken.
11844417 fflush(file_debug);
472
1/2
✓ Branch 0 taken 11844417 times.
✗ Branch 1 not taken.
11844417 if (file_debug == stderr)
473 11844417 pthread_mutex_unlock(&lock_stderr);
474
475 11844417 pthread_mutex_unlock(&lock_debug);
476 }
477 #endif
478
479
2/2
✓ Branch 0 taken 3547570 times.
✓ Branch 1 taken 11933137 times.
15480707 if (mask & kLogStdout) {
480 3547570 pthread_mutex_lock(&lock_stdout);
481
2/2
✓ Branch 0 taken 3541270 times.
✓ Branch 1 taken 6464 times.
3547734 if (mask & kLogShowSource)
482
1/2
✓ Branch 1 taken 3541270 times.
✗ Branch 2 not taken.
3541270 printf("(%s) ", module_names[source]);
483
1/2
✓ Branch 1 taken 3547734 times.
✗ Branch 2 not taken.
3547734 printf("%s", msg);
484
2/2
✓ Branch 0 taken 3547647 times.
✓ Branch 1 taken 87 times.
3547734 if (!(mask & kLogNoLinebreak))
485
1/2
✓ Branch 1 taken 3547647 times.
✗ Branch 2 not taken.
3547647 printf("\n");
486
1/2
✓ Branch 1 taken 3547734 times.
✗ Branch 2 not taken.
3547734 fflush(stdout);
487 3547734 pthread_mutex_unlock(&lock_stdout);
488 }
489
490
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 15480748 times.
15480871 if (mask & kLogStderr) {
491 123 pthread_mutex_lock(&lock_stderr);
492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
123 if (mask & kLogShowSource)
493 fprintf(stderr, "(%s) ", module_names[source]);
494
1/2
✓ Branch 1 taken 123 times.
✗ Branch 2 not taken.
123 fprintf(stderr, "%s", msg);
495
1/2
✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
123 if (!(mask & kLogNoLinebreak))
496
1/2
✓ Branch 1 taken 123 times.
✗ Branch 2 not taken.
123 fprintf(stderr, "\n");
497
1/2
✓ Branch 1 taken 123 times.
✗ Branch 2 not taken.
123 fflush(stderr);
498 123 pthread_mutex_unlock(&lock_stderr);
499 }
500
501
2/2
✓ Branch 0 taken 28781 times.
✓ Branch 1 taken 15452090 times.
15480871 if (mask & (kLogSyslog | kLogSyslogWarn | kLogSyslogErr)) {
502
2/2
✓ Branch 0 taken 20052 times.
✓ Branch 1 taken 8729 times.
28781 if (usyslog_dest) {
503
1/2
✓ Branch 2 taken 20052 times.
✗ Branch 3 not taken.
20052 string fmt_msg(msg);
504
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 20000 times.
20052 if (syslog_prefix)
505
4/8
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 52 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 52 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 52 times.
✗ Branch 12 not taken.
52 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
506 time_t rawtime;
507 20052 time(&rawtime);
508 char fmt_time[26];
509 20052 ctime_r(&rawtime, fmt_time);
510
3/6
✓ Branch 2 taken 20052 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20052 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 20052 times.
✗ Branch 9 not taken.
20052 fmt_msg = string(fmt_time, 24) + " " + fmt_msg;
511
1/2
✓ Branch 1 taken 20052 times.
✗ Branch 2 not taken.
20052 fmt_msg.push_back('\n');
512
1/2
✓ Branch 1 taken 20052 times.
✗ Branch 2 not taken.
20052 LogMicroSyslog(fmt_msg);
513 20052 } else {
514 8729 int level = syslog_level;
515
2/2
✓ Branch 0 taken 4119 times.
✓ Branch 1 taken 4610 times.
8729 if (mask & kLogSyslogWarn)
516 4119 level = LOG_WARNING;
517
2/2
✓ Branch 0 taken 1459 times.
✓ Branch 1 taken 7270 times.
8729 if (mask & kLogSyslogErr)
518 1459 level = LOG_ERR;
519
2/2
✓ Branch 0 taken 4125 times.
✓ Branch 1 taken 4604 times.
8729 if (syslog_prefix) {
520
1/2
✓ Branch 1 taken 4125 times.
✗ Branch 2 not taken.
4125 syslog(syslog_facility | level, "(%s) %s", syslog_prefix, msg);
521 } else {
522
1/2
✓ Branch 1 taken 4484 times.
✗ Branch 2 not taken.
4604 syslog(syslog_facility | level, "%s", msg);
523 }
524 }
525 }
526
527
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 15480691 times.
15480751 if (mask & (kLogCustom0 | kLogCustom1 | kLogCustom2)) {
528
1/2
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
60 string fmt_msg(msg);
529
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 45 times.
60 if (syslog_prefix)
530
4/8
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 15 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 12 not taken.
15 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
531
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 if (!(mask & kLogNoLinebreak))
532
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 fmt_msg += "\n";
533
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 30 times.
60 if (mask & kLogCustom0)
534
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 LogCustom(0, fmt_msg);
535
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 45 times.
60 if (mask & kLogCustom1)
536
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 LogCustom(1, fmt_msg);
537
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 45 times.
60 if (mask & kLogCustom2)
538
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 LogCustom(2, fmt_msg);
539 60 }
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 15480737 times.
✓ Branch 1 taken 14 times.
15480751 if (!(mask & kLogSensitive))
545
3/6
✓ Branch 2 taken 15480723 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15480742 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 15480757 times.
✗ Branch 9 not taken.
15480737 g_log_buffer.Append(LogBufferEntry(source, mask, msg));
546
547 15480771 free(msg);
548 }
549 CVMFS_EXPORT
550 15558019 void LogCvmfs(const LogSource source, const int mask, const char *format, ...) {
551 va_list variadic_list;
552 15558019 va_start(variadic_list, format);
553
1/2
✓ Branch 1 taken 15558904 times.
✗ Branch 2 not taken.
15558019 vLogCvmfs(source, mask, format, variadic_list);
554 15558904 va_end(variadic_list);
555 15558904 }
556
557 96 std::vector<LogBufferEntry> GetLogBuffer() { return g_log_buffer.GetBuffer(); }
558
559 14 void ClearLogBuffer() { g_log_buffer.Clear(); }
560
561 63 void PrintError(const string &message) {
562 63 LogCvmfs(kLogCvmfs, kLogStderr, "[ERROR] %s", message.c_str());
563 63 }
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 276 void SetLogCustomFile(unsigned id, const std::string &filename) {
574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 276 times.
276 assert(id < kMaxCustomlog);
575 276 pthread_mutex_lock(&customlog_locks[id]);
576
577
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 231 times.
276 if (customlog_fds[id] >= 0) {
578 45 close(customlog_fds[id]);
579 45 customlog_fds[id] = -1;
580 }
581
582
2/2
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 48 times.
276 if (filename.empty()) {
583
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 183 times.
228 delete customlog_dests[id];
584 228 customlog_dests[id] = NULL;
585 228 pthread_mutex_unlock(&customlog_locks[id]);
586 228 return;
587 }
588
589 48 customlog_fds[id] = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 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 48 times.
48 delete customlog_dests[id];
597
1/2
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
48 customlog_dests[id] = new string(filename);
598
599 48 pthread_mutex_unlock(&customlog_locks[id]);
600 }
601
602
603 60 static void LogCustom(unsigned id, const std::string &message) {
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 assert(id < kMaxCustomlog);
605
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (message.size() == 0)
606 return;
607
608 60 pthread_mutex_lock(&customlog_locks[id]);
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 assert(customlog_fds[id] >= 0);
610
611 60 const bool retval_b = SafeWrite(customlog_fds[id], message.data(),
612 message.size());
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 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 60 const int retval_i = fsync(customlog_fds[id]);
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 assert(retval_i == 0);
621
622 60 pthread_mutex_unlock(&customlog_locks[id]);
623 }
624
625
626 76 void LogShutdown() {
627
2/4
✓ Branch 2 taken 76 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 76 times.
✗ Branch 6 not taken.
76 SetLogMicroSyslog("");
628
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 76 times.
304 for (unsigned i = 0; i < kMaxCustomlog; ++i)
629
2/4
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 228 times.
✗ Branch 6 not taken.
228 SetLogCustomFile(i, "");
630 76 }
631
632
633 #ifdef CVMFS_NAMESPACE_GUARD
634 } // namespace CVMFS_NAMESPACE_GUARD
635 #endif
636