Skip to content

Adding an event to sysdig

Loris Degioanni edited this page Feb 14, 2016 · 9 revisions

This document contains the list of steps to follow in order to add a new event to sysdig. It's very rough and will be improved in the future. For the moment, its goal is acting as a reference, showing all of the places that need to be modified.

Sysdig events can come from any place inside (and outside) the kernel, but for sake of simplicity we will make the assumption that the new event that we want to add comes from a tracepoint.

Step 1: Define a new event ID

The event ID needs to be added at the end of the ppm_event_type enumeration in ppm_events_public.h. Make sure not to introduce gaps in the numbering, and make sure to always add two IDs, one for enter and one for exit. The exit event can be ignored, but it needs to be there.

Also, remember to increase PPM_EVENT_MAX.

Step 2: Define the format of your event

Add your event definition at the end of the g_event_info array in driver/event_table.c AND userspace/libscap/event_table.c.

Yes, there are two copies of that file, and they need to be kept in sync. The reason is separation between user code and the kernel code, with the goal of potentially becoming part of the mainline kernel in the future.

There must be two entries here as well, one for enter and one for exit, and the exit one can just be a dummy one.

Step 3: Add the callback for your tracepoint

This is the function that will be called by the kernel every time the tracepoint is hit. The prototype will depend of the tracepoint you intercept. Here's, as an example, the sched_switch callback from the sysdig driver.

#ifdef CAPTURE_CONTEXT_SWITCHES
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
TRACEPOINT_PROBE(sched_switch_probe, struct rq *rq, struct task_struct *prev, struct task_struct *next)
#else
TRACEPOINT_PROBE(sched_switch_probe, struct task_struct *prev, struct task_struct *next)
#endif
{
	record_event(PPME_SCHEDSWITCHEX_E,
		NULL,
		-1,
		0,
		prev,
		next);
}
#endif

The tracepoint callback will need to interpret the tracepoint parameters and then call record_event, with the event ID that you've+ just defined as the first argument.

Step 4: Register your tracepoint

Add a call to compat_register_trace in ppm_open (driver/main.c) to register your tracepoint and make it point to the callback defined in step 2.

Also make sure to call compat_unregister_trace in ppm_open and ppm_release to properly disconnect your tracepoint.

Step 5: Implement the filler

Fillers are functions that take raw event arguments and pack them into the sysdig-probe buffer. They are implemented in driver/ppm_fillers.c.

You will need to:

  • declare your tracepoint filler prototype in the following way: static int f_my_event(struct event_filler_arguments *args);
  • implement your filler. You can use the other fillers in ppm_fillers.c as a reference.
  • add your filler to the g_ppm_events array

Done!

At this point, your event should be recognized and decoded by sysdig. You should also be able to use its fields for filters, output formatting and chisels.

Unless you need custom state for the event, or you want to create new filter fields for it. In that case follow the following two steps.

Step 6: parse the event at user level

If your event requires special parsing or contains information that influences sysdig state, you might need to parse it in libsinsp. In order to do so, you will have to edit sinsp_parser::process_event in libsinsp/parsers.cpp.

Step 7: add filter fields

If you want to add new filter fields related to your event, the place to edit is libsinsp/filterchecks.cpp. This is the file where currently every filter field is implemented, and you can use the existing filtering classes as references.

An example

This commit adds the support of the setns system call to the driver. It offers a good summary of the step listed above.