---
title: 'Go API'
sidebar_position: 20
description: 'How to run Gadgets from a Golang application'
---

import CodeBlock from '@theme/CodeBlock';

This document describes how to use the API provided by Inspektor Gadget to run
Gadgets and consume data produced by them from a Golang application.

## Concepts

Let's describe some concepts before jumping to the code.

### Runtime

A runtime is the component that runs the Gadgets. Inspektor Gadget provides two
runtimes:
- [local](https://pkg.go.dev/github.com/inspektor-gadget/inspektor-gadget@%IG_BRANCH%/pkg/runtime/local):
Used to run a Gadget on the local host. It's only supported on Linux.
- [grpc](https://pkg.go.dev/github.com/inspektor-gadget/inspektor-gadget@%IG_BRANCH%/pkg/runtime/grpc):
Used to run a Gadget on a remote Linux host or Kubernetes cluster. It's supported on Linux, Windows
and Mac.

### Operators

Operators are the cornerstones of the Inspektor Gadget architecture. They are
modular components responsible for specific tasks, such as loading eBPF
programs, enriching events, sorting output, etc. Inspektor Gadget provides
different operators as described in the [operators](../spec/operators/)
documentation. It is also possible to create custom operators as explained
below.

### Data Sources

A [Data
Source](https://pkg.go.dev/github.com/inspektor-gadget/inspektor-gadget@%IG_BRANCH%/pkg/datasource)
is a mechanism used to transport the data generated by the Gadgets (or
operators) across the different components. Operators can generate, consume and
mutate data and the layout of the data source.

### Gadget Context

The [Gadget
Context](https://pkg.go.dev/github.com/inspektor-gadget/inspektor-gadget@%IG_BRANCH%/pkg/gadget-context)
is the component that glues everything together. This carries information
between operators, runtimes, etc.

## Examples

These examples provide minimal working code to use Gadgets in different ways.
Their source code can be found at
https://github.com/inspektor-gadget/inspektor-gadget/tree/%IG_BRANCH%/examples/gadgets

### Running your first Gadget

Let's start with the minimal code required to run a Gadget. This example shows
how to run the [`trace_open`]( ../gadgets/trace_open.mdx) gadget and print the
events it captures to the terminal in json format.

import SimpleTraceOpen from '!!raw-loader!./_golang/trace_open/main.go';

<CodeBlock language="go">{SimpleTraceOpen}</CodeBlock>

Now let's run it. It'll print all the files being opened on the system.

```bash
$ go run -exec sudo .
{
  "error_raw": 0,
  "fd": 7,
  "flags_raw": 524288,
  "fname": "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/memory.pressure",
  "mode_raw": 0,
  "proc": {
    "comm": "systemd-oomd",
    "creds": {
      "gid": 117,
      "uid": 108
    },
    "mntns_id": 4026532600,
    "parent": {
      "comm": "systemd",
      "pid": 1
    },
    "pid": 1081,
    "tid": 1081
  },
  "timestamp_raw": 750512507929
}
{
  "error_raw": 0,
  "fd": 15,
  "flags_raw": 0,
  "fname": "/sys/class/net/lo/statistics/rx_packets",
  "mode_raw": 0,
  "proc": {
    "comm": "gnome-system-mo",
    "creds": {
      "gid": 1000,
      "uid": 1000
    },
    "mntns_id": 4026531841,
    "parent": {
      "comm": "gnome-shell",
      "pid": 2601
    },
    "pid": 16039,
    "tid": 16039
  },
  "timestamp_raw": 750917767023
}
...
```

### Running a Gadget from a file

The example above pulls the `trace_open` image from the internet if it's not
already present on the system. This example shows how to run a Gadget from a
file avoiding pulling the image from the internet.

The `image export` command is used to create a tarball with the `trace_open`
image.

```bash
# pull the image if not already present on the system
$ sudo ig image pull trace_open:main

# export the image to a tarball
$ sudo ig image export trace_open:main trace_open.tar
```

import FromFile from '!!raw-loader!./_golang/from_file/main.go';

<CodeBlock language="go">{FromFile}</CodeBlock>

Running this example produces the same results as the previous example.

### Running a Gadget embedded in your application

The example above required you to ship the tarball file together with your
application binary. But you might want to ship the gadget embedded in your
binary, so let's explore how that can be done by using `//go:embed`.

import FromMemory from '!!raw-loader!./_golang/from_memory/main.go';

<CodeBlock language="go">{FromMemory}</CodeBlock>

Again, running this will produce the same results as the previous examples.

### Using operators from Inspektor Gadget

In this example we use some operators provided by Inspektor Gadget to extend the
functionality of your application:

- [LocalManager](../spec/operators/localmanager.md): Enriches events with
container information. Also provides a mechanism to filter events by
container.
- [Formatters](../spec/operators/formatters.md): Provides a prettier (or
human-readable) representation of some fields like timestamps, etc.

Parameters for each operator are passed as a map of strings using the
fully qualified name of the parameter as the key.

import Operators from '!!raw-loader!./_golang/operators/main.go';

<CodeBlock language="go">{Operators}</CodeBlock>

Before running the example, let's create a couple of containers that will
generate some events:

```bash
$ docker run --name mycontainer --rm -d busybox sh -c "while true; do cat /dev/null; sleep 1; done"
$ docker run --name foocontainer --rm -d busybox sh -c "while true; do cat /dev/null; sleep 1; done"
```

Now, let's run the example.

```bash
$ go run -exec sudo .
{
  "error": "",
  "error_raw": 0,
  "fd": 3,
  "flags_raw": 0,
  "fname": "/dev/null",
  "k8s": {
    "containerName": "",
    "hostnetwork": false,
    "namespace": "",
    "node": "",
    "owner": {
      "kind": "",
      "name": ""
    },
    "podLabels": "",
    "podName": ""
  },
  "mode_raw": 0,
  "proc": {
    "comm": "cat",
    "creds": {
      "gid": 0,
      "uid": 0
    },
    "mntns_id": 4026534339,
    "parent": {
      "comm": "sh",
      "pid": 42678
    },
    "pid": 53660,
    "tid": 53660
  },
  "runtime": {
    "containerId": "1b0ba0f6f7f7251a8dedbee0a836dc3edadeba7444cd56d6afe0989b6007bcd7",
    "containerImageDigest": "sha256:2919d0172f7524b2d8df9e50066a682669e6d170ac0f6a49676d54358fe970b5",
    "containerImageName": "busybox",
    "containerName": "mycontainer",
    "containerPid": 42678,
    "containerStartedAt": 1737743296076978537,
    "runtimeName": "docker"
  },
  "timestamp": "2025-01-24T13:37:35.312976962-05:00",
  "timestamp_raw": 1737743855312976962
}
```

As expected, only events from `mycontainer` are captured and the runtime node
contains all information related to the container creating the events. Also, a
new timestamp field with a human-readable version is present.

Don't forget to remove the containers created above:

```bash
$ docker rm mycontainer foocontainer
```

### Data Source

So far, we've been using the json formatter to convert the events produced by a
Gadget to json. However, if you're only interested in getting specific fields,
it can be more performant to access them directly using a Field Accessor instead
of performing a full json marshaling and unmarshaling.

import Datasource from '!!raw-loader!./_golang/datasource/main.go';

<CodeBlock language="go">{Datasource}</CodeBlock>

Executing this program will output the following:

```bash
$ go run -exec sudo .
command systemd-journal (761) opened /run/log/journal/02962d410aef4be9b1be7d022e8be679/system.journal
command systemd-journal (761) opened /run/log/journal/02962d410aef4be9b1be7d022e8be679/system.journal
command tmux: server (12404) opened /proc/38122/cmdline
command systemd-oomd (1245) opened /proc/meminfo
command systemd-oomd (1245) opened /sys/fs/cgroup/user.slice/user-1001.slice/user@1001.service/memory.pressure
command systemd-oomd (1245) opened /sys/fs/cgroup/user.slice/user-1001.slice/user@1001.service/memory.current
command systemd-oomd (1245) opened /sys/fs/cgroup/user.slice/user-1001.slice/user@1001.service/memory.min
command systemd-oomd (1245) opened /sys/fs/cgroup/user.slice/user-1001.slice/user@1001.service/memory.low
command systemd-oomd (1245) opened /sys/fs/cgroup/user.slice/user-1001.slice/user@1001.service/memory.swap.current
command systemd-oomd (1245) opened /sys/fs/cgroup/user.slice/user-1001.slice/user@1001.service/memory.stat
command systemd-oomd (1245) opened /proc/meminfo
command dbus-daemon (3811) opened /sys/kernel/security/apparmor/.access
command tmux: server (12404) opened /proc/38122/cmdline
command systemd-oomd (1245) opened /proc/meminfo
command systemd-oomd (1245) opened /proc/meminfo
command tmux: server (12404) opened /proc/38122/cmdline
```

### Running Gadgets remotely with the gRPC runtime

All the examples above run the gadgets (and their eBPF parts) locally. The following
examples show how to run gadgets remotely using the gRPC runtime in different
environments (Linux host, Kubernetes cluster, etc.).

#### Linux Host

This example shows how to run a Gadget on a Kubernetes cluster using the gRPC
runtime. In this case, an Inspektor Gadget installation is required on the
Kubernetes cluster. That then also takes care of pulling the Gadget image
from the OCI registry - the client itself does not contact the OCI registry.

import GRPC from '!!raw-loader!./_golang/grpc/main.go';

<CodeBlock language="go">{GRPC}</CodeBlock>

In this case we need to run `ig` in daemon mode:

```bash
$ sudo ig daemon --tls-insecure --host tcp://127.0.0.1:8888
INFO[0000] starting Inspektor Gadget daemon at "tcp://127.0.0.1:8888"
```

Now run the example. Note that in this case running as user "root" is not
needed, because all the privileged operations are happening inside the `ig`
process on the remote side.

```bash
$ go run .
{"comm":"irqbalance","err":0,"fd":6,"flags":0,"fname":"/proc/interrupts","gid":0,"mntns_id":4026533158,"mode":0,"pid":1262,"timestamp":6114008072805,"uid":0}
{"comm":"irqbalance","err":0,"fd":6,"flags":0,"fname":"/proc/stat","gid":0,"mntns_id":4026533158,"mode":0,"pid":1262,"timestamp":6114008961935,"uid":0}
{"comm":"irqbalance","err":0,"fd":6,"flags":0,"fname":"/proc/irq/65/smp_affinity","gid":0,"mntns_id":4026533158,"mode":0,"pid":1262,"timestamp":6114009113261,"uid":0}
{"comm":"irqbalance","err":0,"fd":6,"flags":0,"fname":"/proc/irq/98/smp_affinity","gid":0,"mntns_id":4026533158,"mode":0,"pid":1262,"timestamp":6114009138809,"uid":0}
```

#### Kubernetes Cluster

This example shows how to run a Gadget on a Kubernetes cluster using the gRPC
runtime. In this case, Inspektor Gadget installation is required on the
Kubernetes cluster, and it also takes care of pulling the Gadget image
from the OCI registry so the client doesn't need to contact the OCI registry

import GRPCK8s from '!!raw-loader!./_golang/grpc_kubernetes/main.go';

<CodeBlock language="go">{GRPCK8s}</CodeBlock>

Now let's run the example. See how it has all the Kubernetes metadata
attached to the events:

```bash
$ go run .
{"error":"","fd":14,"fname":"/proc/1/stat","k8s":{"containerName":"coredns","namespace":"kube-system","node":"aks-agentpool-93770793-vmss000000","owner":{},"podName":"coredns-6f776c8fb5-wwtqz"},"mode":"----------","proc":{"comm":"coredns","pid":19588,"tid":20673}}
{"error":"","fd":14,"fname":"/proc/stat","k8s":{"containerName":"coredns","namespace":"kube-system","node":"aks-agentpool-93770793-vmss000000","owner":{},"podName":"coredns-6f776c8fb5-wwtqz"},"mode":"----------","proc":{"comm":"coredns","pid":19588,"tid":20673}}
{"error":"","fd":14,"fname":"/proc/1/fd","k8s":{"containerName":"coredns","namespace":"kube-system","node":"aks-agentpool-93770793-vmss000000","owner":{},"podName":"coredns-6f776c8fb5-wwtqz"},"mode":"----------","proc":{"comm":"coredns","pid":19588,"tid":20673}}
{"error":"","fd":14,"fname":"/proc/1/limits","k8s":{"containerName":"coredns","namespace":"kube-system","node":"aks-agentpool-93770793-vmss000000","owner":{},"podName":"coredns-6f776c8fb5-wwtqz"},"mode":"----------","proc":{"comm":"coredns","pid":19588,"tid":20673}}
```



### Other Examples

There are other examples available in the repo, please check them at
https://github.com/inspektor-gadget/inspektor-gadget/tree/%IG_BRANCH%/examples/gadgets/other
