GCC Code Coverage Report


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