Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70303845 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "perf: remove JSON scripting format"

parents 9f79bbf3 0aaa94a3
Loading
Loading
Loading
Loading
+0 −29
Original line number Diff line number Diff line
perf-script-json-export(1)
====================

NAME
----
perf-script-json-export - Export trace data to JSON

SYNOPSIS
--------
[verse]
'perf script' -g JSON:<script>
'perf script' -g <script.json>
'perf script' -s JSON:<script> [option]*
'perf script' -s <script.json> [option]*

DESCRIPTION
-----------

This perf script option is used to export perf script data using JSON
format.  JSON export extesion is identified either by the 'JSON:'
prefix or the '.json' file extension.

Both command forms export JSON fomatted data.  The '-g'/'--gen-script'
option does not include actual event data.  Only Definitions.  '-s'
version includes events and definition data (by default).

SEE ALSO
--------
linkperf:perf-script[1]
+0 −6
Original line number Diff line number Diff line
@@ -817,12 +817,6 @@ else
  endif
endif

ifdef NO_JSON_EXPORT
	BASIC_CFLAGS += -DNO_JSON_EXPORT
else
	LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-json-export.o
endif

ifdef NO_DEMANGLE
	BASIC_CFLAGS += -DNO_DEMANGLE
else
+0 −1
Original line number Diff line number Diff line
@@ -461,7 +461,6 @@ static void setup_scripting(void)
{
	setup_perl_scripting();
	setup_python_scripting();
	setup_json_export();

	scripting_ops = &default_scripting_ops;
}
+0 −322
Original line number Diff line number Diff line
/*
 * trace-event-json-export.  Export events to JSON format.
 *
 * derived from: trace-event-python.c
 *
 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
 * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

#include "../../perf.h"
#include "../util.h"
#include "../trace-event.h"
#include "../event.h"
#include "../thread.h"

#define FTRACE_MAX_EVENT				\
	((1 << (sizeof(unsigned short) * 8)) - 1)

FILE *ofp;
struct event *events[FTRACE_MAX_EVENT];
static char *cur_field_name;

static void define_value(enum print_arg_type field_type,
			 int id,
			 const char *field_name,
			 const char *field_value,
			 const char *field_str)
{
	const char *handler_name = (field_type == PRINT_SYMBOL) ?
		"define_symbol" : "define_flag";
	unsigned long long value;

	value = eval_flag(field_value);

	fprintf(ofp,
		",\n[\"%s\",%d,{\"field\":\"%s\",\"value\":%llu,\"name\":\"%s\"}]",
		handler_name, id, field_name, value, field_str);
}

static void define_values(enum print_arg_type field_type,
			  struct print_flag_sym *field,
			  int id,
			  const char *field_name)
{
	define_value(field_type, id, field_name, field->value,
			 field->str);

	if (field->next)
		define_values(field_type, field->next, id, field_name);
}

static void define_field(enum print_arg_type field_type,
			 int id,
			 const char *field_name,
			 const char *delim)
{
	if (field_type == PRINT_FLAGS) {
		const char *handler_name = "define_flag_field";
		fprintf(ofp,
			",\n[\"%s\",%d,{\"field\":\"%s\",\"delim\":\"%s\"}]",
			handler_name, id, field_name, delim);
	} else {
		const char *handler_name = "define_symbol_field";
		fprintf(ofp, ",\n[\"%s\",%d,{\"field\":\"%s\"}]",
				handler_name, id, field_name);
	}
}

static void define_event_symbols(struct event *event,
				struct print_arg *args)
{
	switch (args->type) {
	case PRINT_NULL:
		break;
	case PRINT_ATOM:
		define_value(PRINT_FLAGS, event->id, cur_field_name, "0",
				 args->atom.atom);
		break;
	case PRINT_FIELD:
		cur_field_name = args->field.name;
		break;
	case PRINT_FLAGS:
		define_event_symbols(event, args->flags.field);
		define_field(PRINT_FLAGS, event->id, cur_field_name,
				 args->flags.delim);
		define_values(PRINT_FLAGS, args->flags.flags, event->id,
				  cur_field_name);
		break;
	case PRINT_SYMBOL:
		define_event_symbols(event, args->symbol.field);
		define_field(PRINT_SYMBOL, event->id, cur_field_name, NULL);
		define_values(PRINT_SYMBOL, args->symbol.symbols, event->id,
				  cur_field_name);
		break;
	case PRINT_STRING:
		break;
	case PRINT_TYPE:
		define_event_symbols(event, args->typecast.item);
		break;
	case PRINT_OP:
		define_event_symbols(event, args->op.left);
		define_event_symbols(event, args->op.right);
		break;
	default:
		/* we should warn... */
		return;
	}

	if (args->next)
		define_event_symbols(event, args->next);
}

#define prefix(indx) (indx ? "," : "")
static void define_event(struct event *event)
{
	const char *ev_system = event->system;
	const char *ev_name = event->name;
	int indx = 0;
	const char *handler_name = "define_event";
	struct format_field *field = 0;

	fprintf(ofp,
		",\n[\"%s\",%d,{\"system\":\"%s\",\"name\":\"%s\",\"args\":{",
			handler_name, event->id, ev_system, ev_name);

	fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_s", indx);
	indx++;
	fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_ns", indx);
	indx++;
	fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_cpu", indx);
	indx++;
	fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_comm", indx);
	indx++;
	for (field = event->format.common_fields; field; field = field->next) {
		fprintf(ofp, "%s\"%s\":%d", prefix(indx), field->name, indx);
		indx++;
	}
	for (field = event->format.fields; field; field = field->next) {
		fprintf(ofp, "%s\"%s\":%d", prefix(indx), field->name, indx);
		indx++;
	}
	fprintf(ofp, "}}]");
}

static inline struct event *find_cache_event(int type)
{
	struct event *event;

	if (events[type])
		return events[type];

	events[type] = event = trace_find_event(type);
	if (!event)
		return NULL;

	define_event(event);
	define_event_symbols(event, event->print_fmt.args);

	return event;
}

static void json_process_field(int indx, void *data, struct format_field *field)
{
	unsigned long long val;

	if (field->flags & FIELD_IS_STRING) {
		int offset;
		if (field->flags & FIELD_IS_DYNAMIC) {
			offset = *(int *)(data + field->offset);
			offset &= 0xffff;
		} else
			offset = field->offset;
		fprintf(ofp, "%s\"%s\"", prefix(indx), (char *)data + offset);
	} else { /* FIELD_IS_NUMERIC */
		val = read_size(data + field->offset, field->size);
		if (field->flags & FIELD_IS_SIGNED)
			fprintf(ofp, "%s%lld", prefix(indx),
					(long long int) val);
		else
			fprintf(ofp, "%s%llu", prefix(indx), val);
	}
}

static void json_process_event(union perf_event *pevent __unused,
			       struct perf_sample *sample,
			       struct perf_evsel *evsel __unused,
			       struct machine *machine __unused,
			       struct thread *thread)
{
	struct format_field *field;
	unsigned long s, ns;
	struct event *event;
	int type;
	int indx = 0;
	int cpu = sample->cpu;
	void *data = sample->raw_data;
	unsigned long long nsecs = sample->time;
	char *comm = thread->comm;

	type = trace_parse_common_type(data);

	event = find_cache_event(type);
	if (!event)
		die("ug! no event found for type %d", type);

	s = nsecs / NSECS_PER_SEC;
	ns = nsecs - s * NSECS_PER_SEC;

	fprintf(ofp, ",\n[\"event\",%d,[%lu,%lu,%d,\"%s\"",
			type, s, ns, cpu, comm);

	indx += 4;

	for (field = event->format.common_fields; field; field = field->next)
		json_process_field(indx++, data, field);

	for (field = event->format.fields; field; field = field->next)
		json_process_field(indx++, data, field);

	fprintf(ofp , "]]");
}

/*
 * Start trace script
 */
static int json_start_script(const char *script, int argc __unused,
		const char **argv __unused)
{
	int err = 0;

	if (script[0]) {
		ofp = fopen(script, "w");
		if (ofp == NULL) {
			fprintf(stderr, "couldn't open %s\n", script);
			return -EBADF;
		}
	} else
		ofp = stdout;

	fprintf(ofp, "[[\"trace_start\"]");

	return err;
}

/*
 * Stop trace script
 */
static int json_stop_script(void)
{
	int err = 0;

	fprintf(ofp, ",\n[\"trace_end\"]]");

	return err;
}

static int json_generate_script(const char *outfile)
{
	struct event *event = NULL;
	char fname[PATH_MAX];

	snprintf(fname, sizeof(fname), "%s.json", outfile);

	ofp = fopen(fname, "w");

	if (ofp == NULL) {
		fprintf(stderr, "couldn't open %s\n", fname);
		return -EBADF;
	}
	fprintf(ofp, "[[\"generate_start\"]");

	while ((event = trace_find_next_event(event))) {
		define_event(event);
		define_event_symbols(event, event->print_fmt.args);
	}

	fprintf(ofp, ",\n[\"generate_end\"]]");

	fclose(ofp);

	fprintf(stderr, "generated json script: %s\n", fname);

	return 0;
}

struct scripting_ops json_scripting_ops = {
	.name = "JSON",
	.start_script = json_start_script,
	.stop_script = json_stop_script,
	.process_event = json_process_event,
	.generate_script = json_generate_script,
};

void setup_json_export(void)
{
	int err;
	err = script_spec_register("JSON", &json_scripting_ops);
	if (err)
		die("error registering JSON export extension");
}
+0 −1
Original line number Diff line number Diff line
@@ -91,7 +91,6 @@ int script_spec_register(const char *spec, struct scripting_ops *ops);

void setup_perl_scripting(void);
void setup_python_scripting(void);
void setup_json_export(void);

struct scripting_context {
	struct pevent *pevent;