xref: /aosp_15_r20/external/openscreen/util/trace_logging/scoped_trace_operations.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "util/trace_logging/scoped_trace_operations.h"
6 
7 #include "absl/types/optional.h"
8 #include "platform/api/trace_logging_platform.h"
9 #include "platform/base/trace_logging_activation.h"
10 #include "util/osp_logging.h"
11 
12 #if defined(ENABLE_TRACE_LOGGING)
13 
14 namespace openscreen {
15 namespace internal {
16 
17 // static
TraceAsyncEnd(const uint32_t line,const char * file,TraceId id,Error::Code e)18 bool ScopedTraceOperation::TraceAsyncEnd(const uint32_t line,
19                                          const char* file,
20                                          TraceId id,
21                                          Error::Code e) {
22   auto end_time = Clock::now();
23   const CurrentTracingDestination destination;
24   if (destination) {
25     destination->LogAsyncEnd(line, file, end_time, id, e);
26     return true;
27   }
28   return false;
29 }
30 
ScopedTraceOperation(TraceId trace_id,TraceId parent_id,TraceId root_id)31 ScopedTraceOperation::ScopedTraceOperation(TraceId trace_id,
32                                            TraceId parent_id,
33                                            TraceId root_id) {
34   if (traces_ == nullptr) {
35     // Create the stack if it doesnt' exist.
36     traces_ = new TraceStack();
37 
38     // Create a new root node. This will re-call this constructor and add the
39     // root node to the stack before proceeding with the original node.
40     root_node_ = new TraceIdSetter(TraceIdHierarchy::Empty());
41     OSP_DCHECK(!traces_->empty());
42   }
43 
44   // Setting trace id fields.
45   root_id_ = root_id != kUnsetTraceId ? root_id : traces_->top()->root_id_;
46   parent_id_ =
47       parent_id != kUnsetTraceId ? parent_id : traces_->top()->trace_id_;
48   trace_id_ =
49       trace_id != kUnsetTraceId ? trace_id : trace_id_counter_.fetch_add(1);
50 
51   // Add this item to the stack.
52   traces_->push(this);
53   OSP_DCHECK(traces_->size() < 1024);
54 }
55 
~ScopedTraceOperation()56 ScopedTraceOperation::~ScopedTraceOperation() {
57   OSP_CHECK(traces_ != nullptr && !traces_->empty());
58   OSP_CHECK_EQ(traces_->top(), this);
59   traces_->pop();
60 
61   // If there's only one item left, it must be the root node. Deleting the root
62   // node will re-call this destructor and delete the traces_ stack.
63   if (traces_->size() == 1) {
64     OSP_CHECK_EQ(traces_->top(), root_node_);
65     delete root_node_;
66     root_node_ = nullptr;
67   } else if (traces_->empty()) {
68     delete traces_;
69     traces_ = nullptr;
70   }
71 }
72 
73 // static
74 thread_local ScopedTraceOperation::TraceStack* ScopedTraceOperation::traces_ =
75     nullptr;
76 
77 // static
78 thread_local ScopedTraceOperation* ScopedTraceOperation::root_node_ = nullptr;
79 
80 // static
81 std::atomic<std::uint64_t> ScopedTraceOperation::trace_id_counter_{
82     uint64_t{0x01} << (sizeof(TraceId) * 8 - 1)};
83 
TraceLoggerBase(TraceCategory::Value category,const char * name,const char * file,uint32_t line,TraceId current,TraceId parent,TraceId root)84 TraceLoggerBase::TraceLoggerBase(TraceCategory::Value category,
85                                  const char* name,
86                                  const char* file,
87                                  uint32_t line,
88                                  TraceId current,
89                                  TraceId parent,
90                                  TraceId root)
91     : ScopedTraceOperation(current, parent, root),
92       start_time_(Clock::now()),
93       result_(Error::Code::kNone),
94       name_(name),
95       file_name_(file),
96       line_number_(line),
97       category_(category) {}
98 
TraceLoggerBase(TraceCategory::Value category,const char * name,const char * file,uint32_t line,TraceIdHierarchy ids)99 TraceLoggerBase::TraceLoggerBase(TraceCategory::Value category,
100                                  const char* name,
101                                  const char* file,
102                                  uint32_t line,
103                                  TraceIdHierarchy ids)
104     : TraceLoggerBase(category,
105                       name,
106                       file,
107                       line,
108                       ids.current,
109                       ids.parent,
110                       ids.root) {}
111 
~SynchronousTraceLogger()112 SynchronousTraceLogger::~SynchronousTraceLogger() {
113   const CurrentTracingDestination destination;
114   if (destination) {
115     auto end_time = Clock::now();
116     destination->LogTrace(this->name_, this->line_number_, this->file_name_,
117                           this->start_time_, end_time, this->to_hierarchy(),
118                           this->result_);
119   }
120 }
121 
~AsynchronousTraceLogger()122 AsynchronousTraceLogger::~AsynchronousTraceLogger() {
123   const CurrentTracingDestination destination;
124   if (destination) {
125     destination->LogAsyncStart(this->name_, this->line_number_,
126                                this->file_name_, this->start_time_,
127                                this->to_hierarchy());
128   }
129 }
130 
131 TraceIdSetter::~TraceIdSetter() = default;
132 
133 }  // namespace internal
134 }  // namespace openscreen
135 
136 #endif  // defined(ENABLE_TRACE_LOGGING)
137