GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/logging.cc
Date: 2025-11-09 02:35:23
Exec Total Coverage
Lines: 233 343 67.9%
Branches: 157 303 51.8%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * LogCvmfs() handles all message output. It works like printf.
5 * It can log to a debug log file, stdout, stderr, and syslog.
6 * The tracer is a separate module, messages do not overlap with logging.
7 *
8 * The syslog setter routines are not thread-safe. They are meant to be
9 * invoked at the very first, single-threaded stage.
10 *
11 * If DEBUGMSG is undefined, pure debug messages are compiled into no-ops.
12 */
13
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <pthread.h>
17 #include <sys/syslog.h>
18 #include <stdio.h>
19 #include <stdio.h>
20 #include <syslog.h>
21 #include <time.h>
22 #include <unistd.h>
23
24 #include <cassert>
25 #include <cstdarg>
26 #include <cstdio>
27 #include <cstdlib>
28 #include <cstring>
29 #include <ctime>
30 #include <string>
31 #include <vector>
32
33 #include "util/export.h"
34 #include "util/logging_internal.h" // NOLINT(build/include)
35 #include "util/mutex.h"
36 #include "util/platform.h"
37 #include "util/posix.h"
38 #include "util/single_copy.h"
39 #include "util/smalloc.h"
40
41 using namespace std; // NOLINT
42
43 #ifdef CVMFS_NAMESPACE_GUARD
44 namespace CVMFS_NAMESPACE_GUARD {
45 #endif
46
47 static void LogCustom(unsigned id, const std::string &message);
48
49 LogFacilities DefaultLogging::info = kLogSyslog;
50 LogFacilities DefaultLogging::error = kLogSyslogErr;
51
52 void DefaultLogging::Set(LogFacilities info, LogFacilities error) {
53 DefaultLogging::info = info;
54 DefaultLogging::error = error;
55 }
56
57 namespace {
58
59 unsigned gMicroSyslogMax = 500 * 1024; // default: rotate after 500kB
60
61 pthread_mutex_t lock_stdout = PTHREAD_MUTEX_INITIALIZER;
62 pthread_mutex_t lock_stderr = PTHREAD_MUTEX_INITIALIZER;
63 #ifdef DEBUGMSG
64 pthread_mutex_t lock_debug = PTHREAD_MUTEX_INITIALIZER;
65 FILE *file_debug = NULL;
66 string *path_debug = NULL;
67 #endif
68 const char *module_names[] = {
69 "unknown", "cache", "catalog", "sql",
70 "cvmfs", "hash", "download", "compress",
71 "quota", "talk", "monitor", "lru",
72 "fuse stub", "signature", "fs traversal", "catalog traversal",
73 "nfs maps", "publish", "spooler", "concurrency",
74 "utility", "glue buffer", "history", "unionfs",
75 "pathspec", "receiver", "upload s3", "upload http",
76 "s3fanout", "gc", "dns", "authz",
77 "reflog", "kvstore", "telemetry", "curl"};
78 int syslog_facility = LOG_USER;
79 int syslog_level = LOG_NOTICE;
80 char *syslog_prefix = NULL;
81
82 string *usyslog_dest = NULL;
83 int usyslog_fd = -1;
84 int usyslog_fd1 = -1;
85 unsigned usyslog_size = 0;
86 pthread_mutex_t lock_usyslock = PTHREAD_MUTEX_INITIALIZER;
87
88 const unsigned kMaxCustomlog = 3;
89 string *customlog_dests[] = {NULL, NULL, NULL};
90 int customlog_fds[] = {-1, -1, -1};
91 pthread_mutex_t customlog_locks[] = {PTHREAD_MUTEX_INITIALIZER,
92 PTHREAD_MUTEX_INITIALIZER,
93 PTHREAD_MUTEX_INITIALIZER};
94
95 LogLevels max_log_level = kLogNormal;
96 static void (*alt_log_func)(const LogSource source, const int mask,
97 const char *msg) = NULL;
98
99 /**
100 * Circular buffer of the last $n$ calls to LogCvmfs(). Thread-safe class.
101 */
102 class LogBuffer : SingleCopy {
103 public:
104 51 LogBuffer() : next_id_(0) {
105 51 const int retval = pthread_mutex_init(&lock_, NULL);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 assert(retval == 0);
107 51 }
108
109 57 ~LogBuffer() { pthread_mutex_destroy(&lock_); }
110
111 19627989 void Append(const LogBufferEntry &entry) {
112 19627989 const MutexLockGuard lock_guard(lock_);
113 19628076 const size_t idx = next_id_++ % kBufferSize;
114
2/2
✓ Branch 1 taken 807 times.
✓ Branch 2 taken 19627269 times.
19628076 if (idx >= buffer_.size()) {
115
1/2
✓ Branch 1 taken 807 times.
✗ Branch 2 not taken.
807 buffer_.push_back(entry);
116 } else {
117
1/2
✓ Branch 2 taken 19627269 times.
✗ Branch 3 not taken.
19627269 buffer_[idx] = entry;
118 }
119 19628076 }
120
121 146 std::vector<LogBufferEntry> GetBuffer() {
122 // Return a buffer sorted from newest to oldest buffer
123 146 std::vector<LogBufferEntry> sorted_buffer;
124 146 const MutexLockGuard lock_guard(lock_);
125
2/2
✓ Branch 1 taken 822 times.
✓ Branch 2 taken 146 times.
968 for (unsigned i = 1; i <= buffer_.size(); ++i) {
126 822 const unsigned idx = (next_id_ - i) % kBufferSize;
127
1/2
✓ Branch 2 taken 822 times.
✗ Branch 3 not taken.
822 sorted_buffer.push_back(buffer_[idx]);
128 }
129 292 return sorted_buffer;
130 146 }
131
132 22 void Clear() {
133 22 const MutexLockGuard lock_guard(lock_);
134 22 next_id_ = 0;
135 22 buffer_.clear();
136 22 }
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 164 void SetLogSyslogLevel(const int level) {
153
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 164 times.
✗ Branch 3 not taken.
164 switch (level) {
154 case 1:
155 syslog_level = LOG_DEBUG;
156 break;
157 case 2:
158 syslog_level = LOG_INFO;
159 break;
160 164 case 3:
161 164 syslog_level = LOG_NOTICE;
162 164 break;
163 default:
164 syslog_level = LOG_NOTICE;
165 break;
166 }
167 164 }
168
169 108 int GetLogSyslogLevel() {
170
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 switch (syslog_level) {
171 case LOG_DEBUG:
172 return 1;
173 case LOG_INFO:
174 return 2;
175 108 default:
176 108 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 108 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 108 times.
108 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 108 default:
234 108 return -1;
235 }
236 }
237
238 /**
239 * The syslog prefix is used to distinguish multiple repositories in
240 * /var/log/messages
241 */
242 2716 void SetLogSyslogPrefix(const std::string &prefix) {
243
2/2
✓ Branch 0 taken 1373 times.
✓ Branch 1 taken 1343 times.
2716 if (syslog_prefix)
244 1373 free(syslog_prefix);
245
246
2/2
✓ Branch 1 taken 1333 times.
✓ Branch 2 taken 1383 times.
2716 if (prefix == "") {
247 1333 syslog_prefix = NULL;
248 } else {
249 1383 const unsigned len = prefix.length() + 1;
250 1383 syslog_prefix = static_cast<char *>(smalloc(len));
251 1383 syslog_prefix[len - 1] = '\0';
252 1383 memcpy(syslog_prefix, &prefix[0], prefix.length());
253 }
254 2716 }
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 96 void SetLogVerbosity(const LogLevels max_level) { max_log_level = max_level; }
264
265
266 23 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 1612 void SetLogMicroSyslog(const std::string &filename) {
273 1612 pthread_mutex_lock(&lock_usyslock);
274
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1567 times.
1612 if (usyslog_fd >= 0) {
275
1/2
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
45 close(usyslog_fd);
276
1/2
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
45 close(usyslog_fd1);
277 45 usyslog_fd = -1;
278 45 usyslog_fd1 = -1;
279 }
280
281
2/2
✓ Branch 1 taken 1567 times.
✓ Branch 2 taken 45 times.
1612 if (filename == "") {
282
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1522 times.
1567 delete usyslog_dest;
283 1567 usyslog_dest = NULL;
284 1567 pthread_mutex_unlock(&lock_usyslock);
285 1567 return;
286 }
287
288
1/2
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
45 usyslog_fd = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 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 45 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 45 times.
✗ Branch 6 not taken.
45 usyslog_fd1 = open((filename + ".1").c_str(), O_WRONLY | O_CREAT, 0600);
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 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 45 const int retval = platform_fstat(usyslog_fd, &info);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 assert(retval == 0);
303 45 usyslog_size = info.st_size;
304
2/4
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45 times.
✗ Branch 5 not taken.
45 usyslog_dest = new string(filename);
305 45 pthread_mutex_unlock(&lock_usyslock);
306 }
307
308 59 std::string GetLogMicroSyslog() {
309 59 pthread_mutex_lock(&lock_usyslock);
310 59 string result;
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (usyslog_dest)
312 result = *usyslog_dest;
313 59 pthread_mutex_unlock(&lock_usyslock);
314 59 return result;
315 }
316
317 23088 static void LogMicroSyslog(const std::string &message) {
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 23088 times.
23088 if (message.size() == 0)
319 return;
320
321 23088 pthread_mutex_lock(&lock_usyslock);
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23088 times.
23088 if (usyslog_fd < 0) {
323 pthread_mutex_unlock(&lock_usyslock);
324 return;
325 }
326
327 23088 const int written = write(usyslog_fd, message.data(), message.size());
328
3/6
✓ Branch 0 taken 23088 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 23088 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 23088 times.
23088 if ((written < 0) || (static_cast<unsigned>(written) != message.size())) {
329 close(usyslog_fd);
330 usyslog_fd = -1;
331 abort();
332 }
333 23088 int retval = fsync(usyslog_fd);
334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23088 times.
23088 assert(retval == 0);
335 23088 usyslog_size += written;
336
337
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 22881 times.
23088 if (usyslog_size >= gMicroSyslogMax) {
338 // Wipe out usyslog.1 file
339 207 retval = ftruncate(usyslog_fd1, 0);
340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 assert(retval == 0);
341
342 // Copy from usyslog to usyslog.1
343 207 retval = lseek(usyslog_fd, 0, SEEK_SET);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 assert(retval == 0);
345 unsigned char buf[4096];
346 int num_bytes;
347 do {
348
1/2
✓ Branch 1 taken 207 times.
✗ Branch 2 not taken.
207 num_bytes = read(usyslog_fd, buf, 4096);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 assert(num_bytes >= 0);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 if (num_bytes == 0)
351 break;
352
1/2
✓ Branch 1 taken 207 times.
✗ Branch 2 not taken.
207 const int written = write(usyslog_fd1, buf, num_bytes);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 assert(written == num_bytes);
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 } while (num_bytes == 4096);
355 207 retval = lseek(usyslog_fd1, 0, SEEK_SET);
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 assert(retval == 0);
357
358 // Reset usyslog
359 207 retval = lseek(usyslog_fd, 0, SEEK_SET);
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 assert(retval == 0);
361 207 retval = ftruncate(usyslog_fd, 0);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 assert(retval == 0);
363 207 usyslog_size = 0;
364 }
365 23088 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 1431 void SetLogDebugFile(const string &filename) {
373
1/2
✓ Branch 1 taken 1431 times.
✗ Branch 2 not taken.
1431 if (filename == "") {
374
2/4
✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1431 times.
1431 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 1431 times.
1431 delete path_debug;
379 1431 path_debug = NULL;
380 1431 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 157 string GetLogDebugFile() {
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
157 if (path_debug)
407 return *path_debug;
408
1/2
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
157 return "";
409 }
410 #endif
411
412 727 void SetAltLogFunc(void (*fn)(const LogSource source, const int mask,
413 const char *msg)) {
414 727 alt_log_func = fn;
415 727 }
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 19739400 void vLogCvmfs(const LogSource source, const int mask, const char *format,
428 va_list variadic_list) {
429 19739400 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 19739400 const int retval = vasprintf(&msg, format, variadic_list);
444
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 19740385 times.
19740441 assert(retval != -1); // else: out of memory
445
446
2/2
✓ Branch 0 taken 112579 times.
✓ Branch 1 taken 19627806 times.
19740385 if (alt_log_func) {
447
1/2
✓ Branch 1 taken 112579 times.
✗ Branch 2 not taken.
112579 (*alt_log_func)(source, mask, msg);
448 112579 return;
449 }
450
451 #ifdef DEBUGMSG
452
2/2
✓ Branch 0 taken 9789671 times.
✓ Branch 1 taken 9838135 times.
19627806 if (mask & kLogDebug) {
453 9789671 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 9789623 times.
9789721 if (file_debug == NULL)
457 98 file_debug = stderr;
458
459 // Get timestamp
460 time_t rawtime;
461 9789721 time(&rawtime);
462 struct tm now;
463 9789721 localtime_r(&rawtime, &now);
464
465
1/2
✓ Branch 0 taken 9789721 times.
✗ Branch 1 not taken.
9789721 if (file_debug == stderr)
466 9789721 pthread_mutex_lock(&lock_stderr);
467 9789721 fprintf(file_debug, "(%s) %s [%02d-%02d-%04d %02d:%02d:%02d %s]\n",
468 9789721 module_names[source], msg, (now.tm_mon) + 1, now.tm_mday,
469
1/2
✓ Branch 1 taken 9789721 times.
✗ Branch 2 not taken.
9789721 (now.tm_year) + 1900, now.tm_hour, now.tm_min, now.tm_sec,
470 now.tm_zone);
471
1/2
✓ Branch 1 taken 9789721 times.
✗ Branch 2 not taken.
9789721 fflush(file_debug);
472
1/2
✓ Branch 0 taken 9789721 times.
✗ Branch 1 not taken.
9789721 if (file_debug == stderr)
473 9789721 pthread_mutex_unlock(&lock_stderr);
474
475 9789721 pthread_mutex_unlock(&lock_debug);
476 }
477 #endif
478
479
2/2
✓ Branch 0 taken 9705409 times.
✓ Branch 1 taken 9922447 times.
19627856 if (mask & kLogStdout) {
480 9705409 pthread_mutex_lock(&lock_stdout);
481
2/2
✓ Branch 0 taken 9701037 times.
✓ Branch 1 taken 4836 times.
9705873 if (mask & kLogShowSource)
482
1/2
✓ Branch 1 taken 9701037 times.
✗ Branch 2 not taken.
9701037 printf("(%s) ", module_names[source]);
483
1/2
✓ Branch 1 taken 9705873 times.
✗ Branch 2 not taken.
9705873 printf("%s", msg);
484
2/2
✓ Branch 0 taken 9705474 times.
✓ Branch 1 taken 399 times.
9705873 if (!(mask & kLogNoLinebreak))
485
1/2
✓ Branch 1 taken 9705474 times.
✗ Branch 2 not taken.
9705474 printf("\n");
486
1/2
✓ Branch 1 taken 9705873 times.
✗ Branch 2 not taken.
9705873 fflush(stdout);
487 9705873 pthread_mutex_unlock(&lock_stdout);
488 }
489
490
2/2
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 19628032 times.
19628320 if (mask & kLogStderr) {
491 288 pthread_mutex_lock(&lock_stderr);
492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
288 if (mask & kLogShowSource)
493 fprintf(stderr, "(%s) ", module_names[source]);
494
1/2
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
288 fprintf(stderr, "%s", msg);
495
1/2
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
288 if (!(mask & kLogNoLinebreak))
496
1/2
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
288 fprintf(stderr, "\n");
497
1/2
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
288 fflush(stderr);
498 288 pthread_mutex_unlock(&lock_stderr);
499 }
500
501
2/2
✓ Branch 0 taken 29948 times.
✓ Branch 1 taken 19598372 times.
19628320 if (mask & (kLogSyslog | kLogSyslogWarn | kLogSyslogErr)) {
502
2/2
✓ Branch 0 taken 23088 times.
✓ Branch 1 taken 6860 times.
29948 if (usyslog_dest) {
503
1/2
✓ Branch 2 taken 23088 times.
✗ Branch 3 not taken.
23088 string fmt_msg(msg);
504
1/2
✓ Branch 0 taken 23088 times.
✗ Branch 1 not taken.
23088 if (syslog_prefix)
505
4/8
✓ Branch 2 taken 23088 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 23088 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 23088 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 23088 times.
✗ Branch 12 not taken.
23088 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
506 time_t rawtime;
507 23088 time(&rawtime);
508 char fmt_time[26];
509 23088 ctime_r(&rawtime, fmt_time);
510
3/6
✓ Branch 2 taken 23088 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 23088 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 23088 times.
✗ Branch 9 not taken.
23088 fmt_msg = string(fmt_time, 24) + " " + fmt_msg;
511
1/2
✓ Branch 1 taken 23088 times.
✗ Branch 2 not taken.
23088 fmt_msg.push_back('\n');
512
1/2
✓ Branch 1 taken 23088 times.
✗ Branch 2 not taken.
23088 LogMicroSyslog(fmt_msg);
513 23088 } else {
514 6860 int level = syslog_level;
515
2/2
✓ Branch 0 taken 2458 times.
✓ Branch 1 taken 4402 times.
6860 if (mask & kLogSyslogWarn)
516 2458 level = LOG_WARNING;
517
2/2
✓ Branch 0 taken 2271 times.
✓ Branch 1 taken 4589 times.
6860 if (mask & kLogSyslogErr)
518 2271 level = LOG_ERR;
519
2/2
✓ Branch 0 taken 2404 times.
✓ Branch 1 taken 4456 times.
6860 if (syslog_prefix) {
520
1/2
✓ Branch 1 taken 2404 times.
✗ Branch 2 not taken.
2404 syslog(syslog_facility | level, "(%s) %s", syslog_prefix, msg);
521 } else {
522
1/2
✓ Branch 1 taken 4205 times.
✗ Branch 2 not taken.
4456 syslog(syslog_facility | level, "%s", msg);
523 }
524 }
525 }
526
527
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 19627973 times.
19628069 if (mask & (kLogCustom0 | kLogCustom1 | kLogCustom2)) {
528
1/2
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
96 string fmt_msg(msg);
529
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 72 times.
96 if (syslog_prefix)
530
4/8
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 24 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 24 times.
✗ Branch 12 not taken.
24 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
531
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (!(mask & kLogNoLinebreak))
532
1/2
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
96 fmt_msg += "\n";
533
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 48 times.
96 if (mask & kLogCustom0)
534
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 LogCustom(0, fmt_msg);
535
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 72 times.
96 if (mask & kLogCustom1)
536
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 LogCustom(1, fmt_msg);
537
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 72 times.
96 if (mask & kLogCustom2)
538
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 LogCustom(2, fmt_msg);
539 96 }
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 19628018 times.
✓ Branch 1 taken 51 times.
19628069 if (!(mask & kLogSensitive))
545
3/6
✓ Branch 2 taken 19628018 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 19628047 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 19628076 times.
✗ Branch 9 not taken.
19628018 g_log_buffer.Append(LogBufferEntry(source, mask, msg));
546
547 19628069 free(msg);
548 }
549 CVMFS_EXPORT
550 19739389 void LogCvmfs(const LogSource source, const int mask, const char *format, ...) {
551 va_list variadic_list;
552 19739389 va_start(variadic_list, format);
553
1/2
✓ Branch 1 taken 19740648 times.
✗ Branch 2 not taken.
19739389 vLogCvmfs(source, mask, format, variadic_list);
554 19740648 va_end(variadic_list);
555 19740648 }
556
557 146 std::vector<LogBufferEntry> GetLogBuffer() { return g_log_buffer.GetBuffer(); }
558
559 22 void ClearLogBuffer() { g_log_buffer.Clear(); }
560
561 90 void PrintError(const string &message) {
562 90 LogCvmfs(kLogCvmfs, kLogStderr, "[ERROR] %s", message.c_str());
563 90 }
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 417 void SetLogCustomFile(unsigned id, const std::string &filename) {
574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 417 times.
417 assert(id < kMaxCustomlog);
575 417 pthread_mutex_lock(&customlog_locks[id]);
576
577
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 345 times.
417 if (customlog_fds[id] >= 0) {
578 72 close(customlog_fds[id]);
579 72 customlog_fds[id] = -1;
580 }
581
582
2/2
✓ Branch 1 taken 342 times.
✓ Branch 2 taken 75 times.
417 if (filename.empty()) {
583
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 270 times.
342 delete customlog_dests[id];
584 342 customlog_dests[id] = NULL;
585 342 pthread_mutex_unlock(&customlog_locks[id]);
586 342 return;
587 }
588
589 75 customlog_fds[id] = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 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 75 times.
75 delete customlog_dests[id];
597
1/2
✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
75 customlog_dests[id] = new string(filename);
598
599 75 pthread_mutex_unlock(&customlog_locks[id]);
600 }
601
602
603 96 static void LogCustom(unsigned id, const std::string &message) {
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 assert(id < kMaxCustomlog);
605
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
96 if (message.size() == 0)
606 return;
607
608 96 pthread_mutex_lock(&customlog_locks[id]);
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 assert(customlog_fds[id] >= 0);
610
611 96 const bool retval_b = SafeWrite(customlog_fds[id], message.data(),
612 message.size());
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 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 96 const int retval_i = fsync(customlog_fds[id]);
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 assert(retval_i == 0);
621
622 96 pthread_mutex_unlock(&customlog_locks[id]);
623 }
624
625
626 114 void LogShutdown() {
627
2/4
✓ Branch 2 taken 114 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 114 times.
✗ Branch 6 not taken.
114 SetLogMicroSyslog("");
628
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 114 times.
456 for (unsigned i = 0; i < kMaxCustomlog; ++i)
629
2/4
✓ Branch 2 taken 342 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 342 times.
✗ Branch 6 not taken.
342 SetLogCustomFile(i, "");
630 114 }
631
632
633 #ifdef CVMFS_NAMESPACE_GUARD
634 } // namespace CVMFS_NAMESPACE_GUARD
635 #endif
636