quill
BacktraceStorage.h
1 
7 #pragma once
8 
9 #include "quill/backend/TransitEvent.h"
10 #include "quill/core/Attributes.h"
11 
12 #include <cstdint>
13 #include <functional>
14 #include <string>
15 #include <string_view>
16 #include <utility>
17 #include <vector>
18 
19 QUILL_BEGIN_NAMESPACE
20 
21 namespace detail
22 {
29 {
30 public:
31  BacktraceStorage() = default;
32 
33  /***/
34  void store(TransitEvent transit_event, std::string_view const& thread_id, std::string_view const& thread_name)
35  {
36  if (_capacity == 0)
37  {
38  return;
39  }
40 
41  if (_stored_events.size() < _capacity)
42  {
43  // We are still growing the vector to max capacity
44  _stored_events.emplace_back(std::string{thread_id}, std::string{thread_name}, std::move(transit_event));
45  }
46  else
47  {
48  // Store the object in the vector, replacing the previous
49  StoredTransitEvent& ste = _stored_events[_index];
50 
51  ste = StoredTransitEvent{std::string{thread_id}, std::string{thread_name}, std::move(transit_event)};
52 
53  // Update the index wrapping around the vector capacity
54  if (_index < _capacity - 1)
55  {
56  _index += 1;
57  }
58  else
59  {
60  _index = 0;
61  }
62  }
63  }
64 
65  /***/
66  void process(std::function<void(TransitEvent const&, std::string_view thread_id, std::string_view thread_name)> const& callback)
67  {
68  // we found stored messages for this logger
69  size_t index = _index;
70 
71  // Iterate retrieved records in order from first message using index
72  for (size_t i = 0; i < _stored_events.size(); ++i)
73  {
74  // Give to the user callback the thread id and the RecordBase pointer
75  callback(_stored_events[index].transit_event, _stored_events[index].thread_id,
76  _stored_events[index].thread_name);
77 
78  // We wrap around to iterate all messages
79  if (index < _stored_events.size() - 1)
80  {
81  index += 1;
82  }
83  else
84  {
85  index = 0;
86  }
87  }
88 
89  // finally, clean all messages
90  _stored_events.clear();
91  _index = 0;
92  }
93 
94  /***/
95  void set_capacity(uint32_t capacity)
96  {
97  if (_capacity != capacity)
98  {
99  _capacity = capacity;
100  _index = 0;
101  _stored_events.clear();
102  _stored_events.reserve(_capacity);
103  }
104  }
105 
106 private:
107  struct StoredTransitEvent
108  {
109  StoredTransitEvent(std::string thread_id, std::string thread_name, TransitEvent transit_event)
110  : thread_id(std::move(thread_id)),
111  thread_name(std::move(thread_name)),
112  transit_event(std::move(transit_event))
113  {
114  }
115 
120  std::string thread_id;
121  std::string thread_name;
122  TransitEvent transit_event;
123  };
124 
125 private:
126  uint32_t _capacity{0};
127  uint32_t _index{0};
128  std::vector<StoredTransitEvent> _stored_events;
129 };
130 } // namespace detail
131 
132 QUILL_END_NAMESPACE
Stores N max messages per logger name in a vector.
Definition: BacktraceStorage.h:28
Definition: TransitEvent.h:33
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:28