GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/tracer.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 3 5 60.0%
Branches: 1 2 50.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_TRACER_H_
6 #define CVMFS_TRACER_H_ 1
7
8 #include <inttypes.h>
9 #include <pthread.h>
10 #include <sys/time.h>
11
12 #include <cstdio>
13 #include <string>
14
15 #include "shortstring.h"
16 #include "util/atomic.h"
17 #include "util/single_copy.h"
18
19 /**
20 * Tracer is a thread-safe logging helper. It uses a ring buffer
21 * and spawns a helper thread, that flushes the messages onto the disk
22 * when necessary. The output file is in csv format. Usually tracing
23 * a message is a lock-free process, which therefore should have minimal
24 * overhead.
25 *
26 * This is _not_ supposed to be a debugging system. It is optimized for
27 * speed and does not try to gather any additional information (like
28 * threadid, status of variables, etc.).
29 *
30 * Csv output is adapted from libcsv.
31 *
32 * \todo If anything goes wrong, the whole thing breaks down on assertion. This
33 * might be not desired behavior.
34 */
35 class Tracer : SingleCopy {
36 public:
37 enum TraceEvents {
38 kEventOpen = 1,
39 kEventOpenDir,
40 kEventReadlink,
41 kEventLookup,
42 kEventStatFs,
43 kEventGetAttr,
44 kEventListAttr,
45 kEventGetXAttr
46 };
47
48 Tracer();
49 ~Tracer();
50
51 void Activate(const int buffer_size, const int flush_threshold,
52 const std::string &trace_file);
53 void Spawn();
54 void Flush();
55 337962 void inline __attribute__((used)) Trace(const int event,
56 const PathString &path,
57 const std::string &msg)
58 {
59
1/2
✓ Branch 0 taken 338288 times.
✗ Branch 1 not taken.
337962 if (active_) DoTrace(event, path, msg);
60 346372 }
61
62 bool inline __attribute__((used)) IsActive() {
63 return active_;
64 }
65
66 private:
67 /**
68 * Code of the first log line in the trace file.
69 */
70 static const int kEventStart = -1;
71 /**
72 * Code of the lasr log line in the trace file.
73 */
74 static const int kEventStop = -2;
75 /**
76 * Manual flush
77 */
78 static const int kEventFlush = -3;
79
80 /**
81 * Contents of a single log line.
82 */
83 struct BufferEntry {
84 /**
85 * This is currently with milliseconds precision (using gettimeofday).
86 */
87 timeval time_stamp;
88 /**
89 * arbitrary code, negative codes are reserved for internal use.
90 */
91 int code;
92 PathString path; /**< The path that is subject to the trace */
93 std::string msg;
94 };
95
96 static void *MainFlush(void *data);
97 void GetTimespecRel(const int64_t ms, timespec *ts);
98 int WriteCsvFile(FILE *fp, const std::string &field);
99 int32_t DoTrace(const int event,
100 const PathString &path,
101 const std::string &msg);
102
103 bool active_;
104 bool spawned_;
105 std::string trace_file_;
106 int buffer_size_;
107 int flush_threshold_;
108 BufferEntry *ring_buffer_;
109 /**
110 * Has the same size as the ring buffer. If a message is actually copied to the
111 * ring buffer memory, the respective flag is set to 1. Flags are reset to 0 by
112 * the flush thread.
113 */
114 atomic_int32 *commit_buffer_;
115 pthread_t thread_flush_;
116 pthread_cond_t sig_flush_;
117 pthread_mutex_t sig_flush_mutex_;
118 pthread_cond_t sig_continue_trace_;
119 pthread_mutex_t sig_continue_trace_mutex_;
120 /**
121 * Starts with 0 and gets incremented by each call to trace. Contains the first
122 * non-used sequence number.
123 */
124 atomic_int32 seq_no_;
125 /**
126 * Starts with 0 and gets incremented by the flush thread. Points to the first
127 * non-flushed message. flushed <= seq_no holds.
128 */
129 atomic_int32 flushed_;
130 atomic_int32 terminate_flush_thread_;
131 atomic_int32 flush_immediately_;
132 };
133
134 #endif // CVMFS_TRACER_H_
135