1 // Copyright (c) 2012 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.
5 #include "base/debug/trace_event_impl.h"
9 #include "base/debug/trace_event.h"
10 #include "base/format_macros.h"
11 #include "base/logging.h"
12 #include "base/stringprintf.h"
17 const char* kATraceMarkerFile
= "/sys/kernel/debug/tracing/trace_marker";
21 const char* category_group
,
23 unsigned long long id
,
25 const char** arg_names
,
26 const unsigned char* arg_types
,
27 const unsigned long long* arg_values
,
28 scoped_ptr
<base::debug::ConvertableToTraceFormat
> convertable_values
[],
29 unsigned char flags
) {
30 std::string out
= base::StringPrintf("%c|%d|%s", phase
, getpid(), name
);
31 if (flags
& TRACE_EVENT_FLAG_HAS_ID
)
32 base::StringAppendF(&out
, "-%" PRIx64
, static_cast<uint64
>(id
));
35 for (int i
= 0; i
< num_args
; ++i
) {
40 std::string::size_type value_start
= out
.length();
41 if (arg_types
[i
] == TRACE_VALUE_TYPE_CONVERTABLE
) {
42 convertable_values
[i
]->AppendAsTraceFormat(&out
);
44 base::debug::TraceEvent::TraceValue value
;
45 value
.as_uint
= arg_values
[i
];
46 base::debug::TraceEvent::AppendValueAsJSON(arg_types
[i
], value
, &out
);
48 // Remove the quotes which may confuse the atrace script.
49 ReplaceSubstringsAfterOffset(&out
, value_start
, "\\\"", "'");
50 ReplaceSubstringsAfterOffset(&out
, value_start
, "\"", "");
51 // Replace chars used for separators with similar chars in the value.
52 std::replace(out
.begin() + value_start
, out
.end(), ';', ',');
53 std::replace(out
.begin() + value_start
, out
.end(), '|', '!');
57 out
+= category_group
;
58 write(g_atrace_fd
, out
.c_str(), out
.size());
66 void TraceLog::StartATrace() {
68 if (g_atrace_fd
== -1) {
69 g_atrace_fd
= open(kATraceMarkerFile
, O_WRONLY
);
70 if (g_atrace_fd
== -1) {
71 LOG(WARNING
) << "Couldn't open " << kATraceMarkerFile
;
73 EnableIncludedCategoryGroups();
78 void TraceLog::StopATrace() {
80 if (g_atrace_fd
!= -1) {
83 EnableIncludedCategoryGroups();
87 void TraceLog::SendToATrace(
89 const char* category_group
,
91 unsigned long long id
,
93 const char** arg_names
,
94 const unsigned char* arg_types
,
95 const unsigned long long* arg_values
,
96 scoped_ptr
<ConvertableToTraceFormat
> convertable_values
[],
97 unsigned char flags
) {
98 if (g_atrace_fd
== -1)
102 case TRACE_EVENT_PHASE_BEGIN
:
103 WriteEvent('B', category_group
, name
, id
,
104 num_args
, arg_names
, arg_types
, arg_values
, convertable_values
,
108 case TRACE_EVENT_PHASE_END
:
109 // Though a single 'E' is enough, here append pid, name and
110 // category_group etc. So that unpaired events can be found easily.
111 WriteEvent('E', category_group
, name
, id
,
112 num_args
, arg_names
, arg_types
, arg_values
, convertable_values
,
116 case TRACE_EVENT_PHASE_INSTANT
:
117 // Simulate an instance event with a pair of begin/end events.
118 WriteEvent('B', category_group
, name
, id
,
119 num_args
, arg_names
, arg_types
, arg_values
, convertable_values
,
121 write(g_atrace_fd
, "E", 1);
124 case TRACE_EVENT_PHASE_COUNTER
:
125 for (int i
= 0; i
< num_args
; ++i
) {
126 DCHECK(arg_types
[i
] == TRACE_VALUE_TYPE_INT
);
127 std::string out
= base::StringPrintf("C|%d|%s-%s",
128 getpid(), name
, arg_names
[i
]);
129 if (flags
& TRACE_EVENT_FLAG_HAS_ID
)
130 StringAppendF(&out
, "-%" PRIx64
, static_cast<uint64
>(id
));
131 StringAppendF(&out
, "|%d|%s",
132 static_cast<int>(arg_values
[i
]), category_group
);
133 write(g_atrace_fd
, out
.c_str(), out
.size());
143 // Must be called with lock_ locked.
144 void TraceLog::ApplyATraceEnabledFlag(unsigned char* category_group_enabled
) {
145 if (g_atrace_fd
== -1)
148 // Don't enable disabled-by-default categories for atrace.
149 const char* category_group
= GetCategoryGroupName(category_group_enabled
);
150 if (strncmp(category_group
, TRACE_DISABLED_BY_DEFAULT(""),
151 strlen(TRACE_DISABLED_BY_DEFAULT(""))) == 0)
154 *category_group_enabled
|= ATRACE_ENABLED
;