Skip to content

Commit

Permalink
Add CI for bpftrace
Browse files Browse the repository at this point in the history
  • Loading branch information
ScriptSathi committed Apr 10, 2024
1 parent 8beba35 commit e3c9361
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/script/bpftrace/hello_world.bt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BEGIN { printf("hello world\n"); }
29 changes: 29 additions & 0 deletions .github/script/bpftrace/trace_open_syscalls.bt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BEGIN
{
printf("Tracing open syscalls... Hit Ctrl-C to end.\n");
printf("%-6s %-16s %4s %3s %s\n", "PID", "COMM", "FD", "ERR", "PATH");
}

tracepoint:syscalls:sys_enter_open,
tracepoint:syscalls:sys_enter_openat
{
@filename[tid] = args.filename;
}

tracepoint:syscalls:sys_exit_open,
tracepoint:syscalls:sys_exit_openat
/@filename[tid]/
{
$ret = args.ret;
$fd = $ret >= 0 ? $ret : -1;
$errno = $ret >= 0 ? 0 : - $ret;

printf("%-6d %-16s %4d %3d %s\n", pid, comm, $fd, $errno,
str(@filename[tid]));
delete(@filename[tid]);
}

END
{
clear(@filename);
}
89 changes: 89 additions & 0 deletions .github/script/run_bpftrace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import sys
import asyncio
import typing
import signal
import re
import logging

AGENT_TIMEOUT = 5

class BPFTraceTestFail(Exception):
pass

async def handle_stdout(stdout: asyncio.StreamReader, notify: asyncio.Event, title: str, check_error: bool = False, pattern: typing.Optional[str] = None) -> bool:
try:
while True:
task_notify = asyncio.create_task(notify.wait())
task_readline = asyncio.create_task(stdout.readline())
done, pending = await asyncio.wait([task_notify, task_readline], return_when=asyncio.FIRST_COMPLETED)

for task in pending:
task.cancel()

if task_readline in done:
output = task_readline.result().decode()
print(f"{title}:", output, end="")

if pattern is not None:
if re.match(pattern, output.strip()):
notify.set()
else:
if pattern == output.strip():
notify.set()

if task_notify in done or stdout.at_eof():
notify.set()
except asyncio.CancelledError:
pass # Masquer l'erreur CancelledError

async def start_agent(cmd_args: typing.List[str], title: str, notify: asyncio.Event, pattern: typing.Optional[str] = None) -> asyncio.Task:
print(" ".join(cmd_args))
process = await asyncio.create_subprocess_exec(*cmd_args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT)
if process:
return asyncio.create_task(handle_stdout(process.stdout, notify, title, check_error=True, pattern=pattern))
else:
return None

async def main():
if len(sys.argv) < 4:
print("Usage: python script.py <bpftime_path> <install_directory> <bpftrace_cmd> <pattern>")
return

bpftime_path = sys.argv[1]
install_directory = sys.argv[2]
bpftrace_cmd = sys.argv[3]

pattern = None
if len(sys.argv) > 4:
pattern = sys.argv[4]

try:
should_exit = asyncio.Event()
agent_out_task = await start_agent(
[bpftime_path, "-i", install_directory, "start", "bpftrace", bpftrace_cmd],
"AGENT",
should_exit,
pattern=pattern
)
test_fail = False

if agent_out_task:
try:
await asyncio.wait_for(should_exit.wait(), AGENT_TIMEOUT)
except asyncio.TimeoutError:
test_fail = True
finally:
if not agent_out_task.cancelled():
agent_out_task.cancel()
if test_fail:
raise BPFTraceTestFail(f"The test with command \"{bpftrace_cmd}\" has failed")
logging.info(f"Test \"{bpftrace_cmd}\" succeed")


finally:
should_exit.set()
if agent_out_task:
agent_out_task.cancel()

if __name__ == "__main__":
asyncio.run(main())
111 changes: 111 additions & 0 deletions .github/workflows/test-bpftrace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
name: Install and test bpftrace

on:
workflow_dispatch:
push:
branches: ["*"]
pull_request:
branches: ['master']

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true

jobs:
build-runtime:
strategy:
matrix:
enable_jit:
- true
- false
container:
- image: ubuntu-2204
name: ubuntu
- image: fedora-39
name: fedora
runs-on: ubuntu-22.04
container:
image: "manjusakalza/bpftime-base-image:${{matrix.container.image}}"
options: --privileged
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Build and install runtime (with llvm-jit)
if: ${{matrix.enable_jit}}
run: |
make release-with-llvm-jit -j
- name: Build and install runtime (without llvm-jit)
if: ${{!matrix.enable_jit}}
run: |
make release -j
- name: Upload build results (without jit)
uses: actions/upload-artifact@v3
if: ${{!matrix.enable_jit}}
with:
name: runtime-package-no-jit-${{matrix.container.name}}
path: ~/.bpftime
- name: Upload build results (with jit)
uses: actions/upload-artifact@v3
if: ${{matrix.enable_jit}}
with:
name: runtime-package-jit-${{matrix.container.name}}
path: ~/.bpftime
install-bpftrace-and-test:
runs-on: "ubuntu-latest"
needs: [build-runtime]
strategy:
matrix:
container:
- image: ubuntu-2204
name: ubuntu
- image: fedora-39
name: fedora
enable_jit:
- true
- false
bpftrace_tests:
- command: /__w/bpftime/bpftime/.github/script/bpftrace/trace_open_syscalls.bt
expected_output: '^\d+\s+\w+(\s+#\d+)?\s+-?\d+\s+-?\d+\s+\S+$'
- command: /__w/bpftime/bpftime/.github/script/bpftrace/hello_world.bt
expected_output: hello world
container:
image: "manjusakalza/bpftime-base-image:${{matrix.container.image}}"
options: --privileged -v /sys/kernel/debug/:/sys/kernel/debug:rw -v /sys/kernel/tracing:/sys/kernel/tracing:rw
steps:
- name: Download prebuilt runtime (with jit)
if: ${{matrix.enable_jit}}
uses: actions/download-artifact@v3
with:
name: runtime-package-jit-${{matrix.container.name}}
path: /app/.bpftime
- name: Download prebuilt runtime (without jit)
if: ${{!matrix.enable_jit}}
uses: actions/download-artifact@v3
with:
name: runtime-package-no-jit-${{matrix.container.name}}
path: /app/.bpftime
- name: Set permissions
run: |
chmod +x /app/.bpftime/*
- name: Show downloaded artifacts
run: |
ls /app/.bpftime
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Install bpftrace
run: |
if [ "${{ matrix.container.name }}" = "ubuntu" ]; then
apt-get update && apt-get install -y bpftrace
elif [ "${{ matrix.container.name }}" = "fedora" ]; then
dnf install -y bpftrace
else
echo "Unsupported container type"
exit 1
fi
- name: Find tree
run: ls /**/*
- name: Run bpftrace commands
shell: bash
run: python3 /__w/bpftime/bpftime/.github/script/run_bpftrace.py "/app/.bpftime/bpftime" "/app/.bpftime" "${{matrix.bpftrace_tests.command}}" "${{matrix.bpftrace_tests.expected_output}}"

0 comments on commit e3c9361

Please sign in to comment.