GCC Code Coverage Report


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