GCC Code Coverage Report


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