GCC Code Coverage Report


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