GCC Code Coverage Report


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