blob: b2cf9c221bcdad914f2d8f8ab709aba6bc595164 [file] [log] [blame]
Ashwin Chaugulef2984452012-08-21 13:27:37 -04001/*
2 * trace-event-json-export. Export events to JSON format.
3 *
4 * derived from: trace-event-python.c
5 *
Duy Truong790f06d2013-02-13 16:38:12 -08006 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
Ashwin Chaugulef2984452012-08-21 13:27:37 -04007 * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <ctype.h>
29#include <errno.h>
30
31#include "../../perf.h"
32#include "../util.h"
33#include "../trace-event.h"
34#include "../event.h"
35#include "../thread.h"
36
37#define FTRACE_MAX_EVENT \
38 ((1 << (sizeof(unsigned short) * 8)) - 1)
39
40FILE *ofp;
41struct event *events[FTRACE_MAX_EVENT];
42static char *cur_field_name;
43
44static void define_value(enum print_arg_type field_type,
45 int id,
46 const char *field_name,
47 const char *field_value,
48 const char *field_str)
49{
50 const char *handler_name = (field_type == PRINT_SYMBOL) ?
51 "define_symbol" : "define_flag";
52 unsigned long long value;
53
54 value = eval_flag(field_value);
55
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -040056 fprintf(ofp,
57 ",\n[\"%s\",%d,{\"field\":\"%s\",\"value\":%llu,\"name\":\"%s\"}]",
Ashwin Chaugulef2984452012-08-21 13:27:37 -040058 handler_name, id, field_name, value, field_str);
59}
60
61static void define_values(enum print_arg_type field_type,
62 struct print_flag_sym *field,
63 int id,
64 const char *field_name)
65{
66 define_value(field_type, id, field_name, field->value,
67 field->str);
68
69 if (field->next)
70 define_values(field_type, field->next, id, field_name);
71}
72
73static void define_field(enum print_arg_type field_type,
74 int id,
75 const char *field_name,
76 const char *delim)
77{
78 if (field_type == PRINT_FLAGS) {
79 const char *handler_name = "define_flag_field";
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -040080 fprintf(ofp,
81 ",\n[\"%s\",%d,{\"field\":\"%s\",\"delim\":\"%s\"}]",
82 handler_name, id, field_name, delim);
Ashwin Chaugulef2984452012-08-21 13:27:37 -040083 } else {
84 const char *handler_name = "define_symbol_field";
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -040085 fprintf(ofp, ",\n[\"%s\",%d,{\"field\":\"%s\"}]",
Ashwin Chaugulef2984452012-08-21 13:27:37 -040086 handler_name, id, field_name);
87 }
88}
89
90static void define_event_symbols(struct event *event,
91 struct print_arg *args)
92{
93 switch (args->type) {
94 case PRINT_NULL:
95 break;
96 case PRINT_ATOM:
97 define_value(PRINT_FLAGS, event->id, cur_field_name, "0",
98 args->atom.atom);
99 break;
100 case PRINT_FIELD:
101 cur_field_name = args->field.name;
102 break;
103 case PRINT_FLAGS:
104 define_event_symbols(event, args->flags.field);
105 define_field(PRINT_FLAGS, event->id, cur_field_name,
106 args->flags.delim);
107 define_values(PRINT_FLAGS, args->flags.flags, event->id,
108 cur_field_name);
109 break;
110 case PRINT_SYMBOL:
111 define_event_symbols(event, args->symbol.field);
112 define_field(PRINT_SYMBOL, event->id, cur_field_name, NULL);
113 define_values(PRINT_SYMBOL, args->symbol.symbols, event->id,
114 cur_field_name);
115 break;
116 case PRINT_STRING:
117 break;
118 case PRINT_TYPE:
119 define_event_symbols(event, args->typecast.item);
120 break;
121 case PRINT_OP:
122 define_event_symbols(event, args->op.left);
123 define_event_symbols(event, args->op.right);
124 break;
125 default:
126 /* we should warn... */
127 return;
128 }
129
130 if (args->next)
131 define_event_symbols(event, args->next);
132}
133
134#define prefix(indx) (indx ? "," : "")
135static void define_event(struct event *event)
136{
137 const char *ev_system = event->system;
138 const char *ev_name = event->name;
139 int indx = 0;
140 const char *handler_name = "define_event";
141 struct format_field *field = 0;
142
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400143 fprintf(ofp,
144 ",\n[\"%s\",%d,{\"system\":\"%s\",\"name\":\"%s\",\"args\":{",
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400145 handler_name, event->id, ev_system, ev_name);
146
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400147 fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_s", indx);
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400148 indx++;
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400149 fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_ns", indx);
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400150 indx++;
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400151 fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_cpu", indx);
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400152 indx++;
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400153 fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_comm", indx);
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400154 indx++;
155 for (field = event->format.common_fields; field; field = field->next) {
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400156 fprintf(ofp, "%s\"%s\":%d", prefix(indx), field->name, indx);
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400157 indx++;
158 }
159 for (field = event->format.fields; field; field = field->next) {
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400160 fprintf(ofp, "%s\"%s\":%d", prefix(indx), field->name, indx);
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400161 indx++;
162 }
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400163 fprintf(ofp, "}}]");
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400164}
165
166static inline struct event *find_cache_event(int type)
167{
168 struct event *event;
169
170 if (events[type])
171 return events[type];
172
173 events[type] = event = trace_find_event(type);
174 if (!event)
175 return NULL;
176
177 define_event(event);
178 define_event_symbols(event, event->print_fmt.args);
179
180 return event;
181}
182
183static void json_process_field(int indx, void *data, struct format_field *field)
184{
185 unsigned long long val;
186
187 if (field->flags & FIELD_IS_STRING) {
188 int offset;
189 if (field->flags & FIELD_IS_DYNAMIC) {
190 offset = *(int *)(data + field->offset);
191 offset &= 0xffff;
192 } else
193 offset = field->offset;
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400194 fprintf(ofp, "%s\"%s\"", prefix(indx), (char *)data + offset);
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400195 } else { /* FIELD_IS_NUMERIC */
196 val = read_size(data + field->offset, field->size);
197 if (field->flags & FIELD_IS_SIGNED)
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400198 fprintf(ofp, "%s%lld", prefix(indx),
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400199 (long long int) val);
200 else
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400201 fprintf(ofp, "%s%llu", prefix(indx), val);
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400202 }
203}
204
205static void json_process_event(union perf_event *pevent __unused,
206 struct perf_sample *sample,
207 struct perf_evsel *evsel __unused,
208 struct machine *machine __unused,
209 struct thread *thread)
210{
211 struct format_field *field;
212 unsigned long s, ns;
213 struct event *event;
214 int type;
215 int indx = 0;
216 int cpu = sample->cpu;
217 void *data = sample->raw_data;
218 unsigned long long nsecs = sample->time;
219 char *comm = thread->comm;
220
221 type = trace_parse_common_type(data);
222
223 event = find_cache_event(type);
224 if (!event)
225 die("ug! no event found for type %d", type);
226
227 s = nsecs / NSECS_PER_SEC;
228 ns = nsecs - s * NSECS_PER_SEC;
229
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400230 fprintf(ofp, ",\n[\"event\",%d,[%lu,%lu,%d,\"%s\"",
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400231 type, s, ns, cpu, comm);
232
233 indx += 4;
234
235 for (field = event->format.common_fields; field; field = field->next)
236 json_process_field(indx++, data, field);
237
238 for (field = event->format.fields; field; field = field->next)
239 json_process_field(indx++, data, field);
240
241 fprintf(ofp , "]]");
242}
243
244/*
245 * Start trace script
246 */
247static int json_start_script(const char *script, int argc __unused,
248 const char **argv __unused)
249{
250 int err = 0;
251
252 if (script[0]) {
253 ofp = fopen(script, "w");
254 if (ofp == NULL) {
255 fprintf(stderr, "couldn't open %s\n", script);
256 return -EBADF;
257 }
258 } else
259 ofp = stdout;
260
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400261 fprintf(ofp, "[[\"trace_start\"]");
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400262
263 return err;
264}
265
266/*
267 * Stop trace script
268 */
269static int json_stop_script(void)
270{
271 int err = 0;
272
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400273 fprintf(ofp, ",\n[\"trace_end\"]]");
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400274
275 return err;
276}
277
278static int json_generate_script(const char *outfile)
279{
280 struct event *event = NULL;
281 char fname[PATH_MAX];
282
283 snprintf(fname, sizeof(fname), "%s.json", outfile);
284
285 ofp = fopen(fname, "w");
286
287 if (ofp == NULL) {
288 fprintf(stderr, "couldn't open %s\n", fname);
289 return -EBADF;
290 }
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400291 fprintf(ofp, "[[\"generate_start\"]");
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400292
293 while ((event = trace_find_next_event(event))) {
294 define_event(event);
295 define_event_symbols(event, event->print_fmt.args);
296 }
297
Ashwin Chaugulea2a758f2012-09-03 11:20:13 -0400298 fprintf(ofp, ",\n[\"generate_end\"]]");
Ashwin Chaugulef2984452012-08-21 13:27:37 -0400299
300 fclose(ofp);
301
302 fprintf(stderr, "generated json script: %s\n", fname);
303
304 return 0;
305}
306
307struct scripting_ops json_scripting_ops = {
308 .name = "JSON",
309 .start_script = json_start_script,
310 .stop_script = json_stop_script,
311 .process_event = json_process_event,
312 .generate_script = json_generate_script,
313};
314
315void setup_json_export(void)
316{
317 int err;
318 err = script_spec_register("JSON", &json_scripting_ops);
319 if (err)
320 die("error registering JSON export extension");
321}
322