GCC Code Coverage Report


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