GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/logging.cc
Date: 2025-06-22 02:36:02
Exec Total Coverage
Lines: 233 343 67.9%
Branches: 156 303 51.5%

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