blob: 4b4b88f5bdda1377522886c6f4c7f06c8effab53 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
#define BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
#include "base/atomicops.h"
#include "base/base_export.h"
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_local.h"
#include "base/trace_event/trace_event_memory_overhead.h"
#include "build/build_config.h"
namespace base {
namespace trace_event {
typedef base::Callback<bool(const char* arg_name)> ArgumentNameFilterPredicate;
typedef base::Callback<bool(const char* category_group_name,
const char* event_name,
ArgumentNameFilterPredicate*)>
ArgumentFilterPredicate;
// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
// class must implement this interface.
class BASE_EXPORT ConvertableToTraceFormat {
public:
ConvertableToTraceFormat() = default;
virtual ~ConvertableToTraceFormat() = default;
// Append the class info to the provided |out| string. The appended
// data must be a valid JSON object. Strings must be properly quoted, and
// escaped. There is no processing applied to the content after it is
// appended.
virtual void AppendAsTraceFormat(std::string* out) const = 0;
virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
std::string ToString() const {
std::string result;
AppendAsTraceFormat(&result);
return result;
}
private:
DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat);
};
const int kTraceMaxNumArgs = 2;
struct TraceEventHandle {
uint32_t chunk_seq;
// These numbers of bits must be kept consistent with
// TraceBufferChunk::kMaxTrunkIndex and
// TraceBufferChunk::kTraceBufferChunkSize (in trace_buffer.h).
unsigned chunk_index : 26;
unsigned event_index : 6;
};
class BASE_EXPORT TraceEvent {
public:
union TraceValue {
bool as_bool;
unsigned long long as_uint;
long long as_int;
double as_double;
const void* as_pointer;
const char* as_string;
};
TraceEvent();
~TraceEvent();
void MoveFrom(std::unique_ptr<TraceEvent> other);
void Initialize(int thread_id,
TimeTicks timestamp,
ThreadTicks thread_timestamp,
char phase,
const unsigned char* category_group_enabled,
const char* name,
const char* scope,
unsigned long long id,
unsigned long long bind_id,
int num_args,
const char* const* arg_names,
const unsigned char* arg_types,
const unsigned long long* arg_values,
std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
unsigned int flags);
void Reset();
void UpdateDuration(const TimeTicks& now, const ThreadTicks& thread_now);
void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
// Serialize event data to JSON
void AppendAsJSON(
std::string* out,
const ArgumentFilterPredicate& argument_filter_predicate) const;
void AppendPrettyPrinted(std::ostringstream* out) const;
static void AppendValueAsJSON(unsigned char type,
TraceValue value,
std::string* out);
TimeTicks timestamp() const { return timestamp_; }
ThreadTicks thread_timestamp() const { return thread_timestamp_; }
char phase() const { return phase_; }
int thread_id() const { return thread_id_; }
TimeDelta duration() const { return duration_; }
TimeDelta thread_duration() const { return thread_duration_; }
const char* scope() const { return scope_; }
unsigned long long id() const { return id_; }
unsigned int flags() const { return flags_; }
unsigned long long bind_id() const { return bind_id_; }
// Exposed for unittesting:
const std::string* parameter_copy_storage() const {
return parameter_copy_storage_.get();
}
const unsigned char* category_group_enabled() const {
return category_group_enabled_;
}
const char* name() const { return name_; }
unsigned char arg_type(size_t index) const { return arg_types_[index]; }
const char* arg_name(size_t index) const { return arg_names_[index]; }
const TraceValue& arg_value(size_t index) const { return arg_values_[index]; }
const ConvertableToTraceFormat* arg_convertible_value(size_t index) const {
return convertable_values_[index].get();
}
#if defined(OS_ANDROID)
void SendToATrace();
#endif
private:
// Note: these are ordered by size (largest first) for optimal packing.
TimeTicks timestamp_;
ThreadTicks thread_timestamp_;
TimeDelta duration_;
TimeDelta thread_duration_;
// scope_ and id_ can be used to store phase-specific data.
const char* scope_;
unsigned long long id_;
TraceValue arg_values_[kTraceMaxNumArgs];
const char* arg_names_[kTraceMaxNumArgs];
std::unique_ptr<ConvertableToTraceFormat>
convertable_values_[kTraceMaxNumArgs];
const unsigned char* category_group_enabled_;
const char* name_;
std::unique_ptr<std::string> parameter_copy_storage_;
// Depending on TRACE_EVENT_FLAG_HAS_PROCESS_ID the event will have either:
// tid: thread_id_, pid: current_process_id (default case).
// tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID).
union {
int thread_id_;
int process_id_;
};
unsigned int flags_;
unsigned long long bind_id_;
unsigned char arg_types_[kTraceMaxNumArgs];
char phase_;
DISALLOW_COPY_AND_ASSIGN(TraceEvent);
};
} // namespace trace_event
} // namespace base
#endif // BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_