1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be
3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file.
4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifndef BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
90d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <stdint.h>
100d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko
1194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory>
12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <stack>
13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <string>
14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <vector>
15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/atomicops.h"
17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/base_export.h"
18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback.h"
19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/containers/hash_tables.h"
200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/macros.h"
21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/observer_list.h"
22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/single_thread_task_runner.h"
23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/string_util.h"
24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/synchronization/condition_variable.h"
25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/synchronization/lock.h"
26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/thread.h"
27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/thread_local.h"
28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/trace_event/trace_event_memory_overhead.h"
290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "build/build_config.h"
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base {
32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass WaitableEvent;
34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass MessageLoop;
35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace trace_event {
37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
380d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkotypedef base::Callback<bool(const char* arg_name)> ArgumentNameFilterPredicate;
390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko
400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkotypedef base::Callback<bool(const char* category_group_name,
410d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko                            const char* event_name,
420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko                            ArgumentNameFilterPredicate*)>
430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    ArgumentFilterPredicate;
440d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// class must implement this interface.
4745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoclass BASE_EXPORT ConvertableToTraceFormat {
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
4945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ConvertableToTraceFormat() {}
5045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  virtual ~ConvertableToTraceFormat() {}
5145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Append the class info to the provided |out| string. The appended
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // data must be a valid JSON object. Strings must be properly quoted, and
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // escaped. There is no processing applied to the content after it is
55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // appended.
56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  virtual void AppendAsTraceFormat(std::string* out) const = 0;
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  std::string ToString() const {
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    std::string result;
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    AppendAsTraceFormat(&result);
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return result;
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
6745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat);
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
700d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkoconst int kTraceMaxNumArgs = 2;
710d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct TraceEventHandle {
730d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  uint32_t chunk_seq;
740d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  // These numbers of bits must be kept consistent with
750d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  // TraceBufferChunk::kMaxTrunkIndex and
760d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  // TraceBufferChunk::kTraceBufferChunkSize (in trace_buffer.h).
770d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  unsigned chunk_index : 26;
780d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  unsigned event_index : 6;
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass BASE_EXPORT TraceEvent {
82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  union TraceValue {
84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    bool as_bool;
85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    unsigned long long as_uint;
86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    long long as_int;
87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    double as_double;
88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    const void* as_pointer;
89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    const char* as_string;
90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  };
91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TraceEvent();
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~TraceEvent();
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
9594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  void MoveFrom(std::unique_ptr<TraceEvent> other);
9645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
9745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  void Initialize(int thread_id,
9845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  TimeTicks timestamp,
9945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  ThreadTicks thread_timestamp,
10045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  char phase,
10145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  const unsigned char* category_group_enabled,
10245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  const char* name,
10345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  const char* scope,
10445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  unsigned long long id,
10545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  unsigned long long bind_id,
10645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  int num_args,
10745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  const char** arg_names,
10845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  const unsigned char* arg_types,
10945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  const unsigned long long* arg_values,
11094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez                  std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
11145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                  unsigned int flags);
112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void Reset();
114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
1150d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  void UpdateDuration(const TimeTicks& now, const ThreadTicks& thread_now);
116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
1170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Serialize event data to JSON
120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void AppendAsJSON(
121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      std::string* out,
122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      const ArgumentFilterPredicate& argument_filter_predicate) const;
123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void AppendPrettyPrinted(std::ostringstream* out) const;
124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void AppendValueAsJSON(unsigned char type,
126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                TraceValue value,
127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::string* out);
128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
1290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  TimeTicks timestamp() const { return timestamp_; }
130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ThreadTicks thread_timestamp() const { return thread_timestamp_; }
131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  char phase() const { return phase_; }
132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int thread_id() const { return thread_id_; }
133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeDelta duration() const { return duration_; }
134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeDelta thread_duration() const { return thread_duration_; }
13545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const char* scope() const { return scope_; }
136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  unsigned long long id() const { return id_; }
1370d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  unsigned int flags() const { return flags_; }
138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Exposed for unittesting:
140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
14145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const std::string* parameter_copy_storage() const {
142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return parameter_copy_storage_.get();
143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const unsigned char* category_group_enabled() const {
146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return category_group_enabled_;
147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const char* name() const { return name_; }
150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_ANDROID)
152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void SendToATrace();
153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Note: these are ordered by size (largest first) for optimal packing.
1570d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  TimeTicks timestamp_;
158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ThreadTicks thread_timestamp_;
159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeDelta duration_;
160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeDelta thread_duration_;
16145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // scope_ and id_ can be used to store phase-specific data.
16245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const char* scope_;
163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  unsigned long long id_;
164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TraceValue arg_values_[kTraceMaxNumArgs];
165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const char* arg_names_[kTraceMaxNumArgs];
16694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<ConvertableToTraceFormat>
16794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez      convertable_values_[kTraceMaxNumArgs];
168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const unsigned char* category_group_enabled_;
169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const char* name_;
17094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<std::string> parameter_copy_storage_;
1710d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  // Depending on TRACE_EVENT_FLAG_HAS_PROCESS_ID the event will have either:
1720d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  //  tid: thread_id_, pid: current_process_id (default case).
1730d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  //  tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID).
1740d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  union {
1750d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    int thread_id_;
1760d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    int process_id_;
1770d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  };
1780d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  unsigned int flags_;
1790d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  unsigned long long bind_id_;
180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  unsigned char arg_types_[kTraceMaxNumArgs];
1810d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  char phase_;
182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DISALLOW_COPY_AND_ASSIGN(TraceEvent);
184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace trace_event
187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif  // BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
190