A Go build instrumentation tool that injects hooks into functions without modifying source files. Add tracing, logging, or metrics to any Go code at build time.
git clone https://github.com/pdelewski/go-build-interceptor
cd go-build-interceptor/hc
go buildThe hc directory contains the hook compiler - the core tool that performs build-time instrumentation.
package myhooks
import (
"fmt"
"time"
"github.com/pdelewski/go-build-interceptor/hooks"
)
func ProvideHooks() []*hooks.Hook {
return []*hooks.Hook{
{
Target: hooks.InjectTarget{
Package: "main",
Function: "myFunction",
},
Hooks: &hooks.InjectFunctions{
Before: "BeforeMyFunction",
After: "AfterMyFunction",
From: "myhooks",
},
},
}
}
func BeforeMyFunction(ctx hooks.HookContext) {
ctx.SetKeyData("startTime", time.Now())
fmt.Printf("[BEFORE] %s.%s()\n", ctx.GetPackageName(), ctx.GetFuncName())
}
func AfterMyFunction(ctx hooks.HookContext) {
if startTime, ok := ctx.GetKeyData("startTime").(time.Time); ok {
fmt.Printf("[AFTER] %s.%s() took %v\n", ctx.GetPackageName(), ctx.GetFuncName(), time.Since(startTime))
}
}Navigate to your Go project directory, then compile with hooks passed as an argument:
cd /path/to/your/project
/path/to/hc --compile path/to/myhooks.go
# or short form
/path/to/hc -c path/to/myhooks.goThis builds your project with the hooks automatically injected.
The project includes ready-to-use instrumentation examples:
instrumentations/hello/generated_hooks.go provides simple before/after tracing for functions in the main package. It logs function entry/exit with execution timing.
# Navigate to your hello example project
cd examples/hello
# Compile with tracing hooks
../../hc/hc -c ../../instrumentations/hello/generated_hooks.go
# Run the instrumented binary
./helloOutput:
[BEFORE] main.main()
[BEFORE] main.foo()
[AFTER] main.foo() completed in 1.002s
[BEFORE] main.bar1()
[AFTER] main.bar1() completed in 500ms
[AFTER] main.main() completed in 1.503s
instrumentations/runtime/runtime_hooks.go provides Goroutine Local Storage (GLS) support by modifying Go's runtime. This enables context propagation across goroutines for distributed tracing.
Important: Runtime instrumentation is required if you need context to propagate between function calls and across goroutines. Without it, each function hook operates in isolation without access to shared trace context. If you only need simple function tracing without context propagation (like basic timing/logging), you can skip runtime hooks.
This example shows three hook capabilities:
- Struct Modification: Adds
otel_trace_contextandotel_baggage_containerfields to the runtimegstruct - File Generation: Creates
runtime_gls.gowith accessor functions - Function Rewriting: Injects context propagation into
newproc1
# Compile with runtime GLS hooks only
./hc/hc -c ./instrumentations/runtime/runtime_hooks.go
# Compile with both runtime and application hooks (recommended for full tracing)
./hc/hc -c ./instrumentations/runtime/runtime_hooks.go,./instrumentations/hello/generated_hooks.goYou can compile with multiple hooks files by specifying them comma-separated:
./hc/hc -c hooks1.go,hooks2.go,hooks3.goOr use the UI file selector to pick multiple files interactively.
The included web UI provides an interactive environment for exploring code, generating hooks, and building.
UI Workflow Demo - Generating hooks, compiling with instrumentation, and debugging the instrumented code:
Linux/macOS:
cd ui
make setup # Install dependencies & build
make run # Run with default projectWindows:
cd ui
build.bat setup # Install dependencies & build
build.bat run # Run with default projectOr manually:
cd ui
npm install monaco-editor@0.45.0
cp -r node_modules/monaco-editor/min/vs static/monaco/
go build -o ui .
./ui -dir /path/to/your/projectOpen http://localhost:9090 in your browser.
- Code Editor - Monaco editor with Go syntax highlighting and LSP support
- Static Call Graph - View function call relationships
- Hook Generation - Select functions and auto-generate hook code
- Build & Run - Compile with hooks and run directly from the UI
- View Functions: Click "Functions" in the View menu to see all functions in your project
- Generate Hooks: Select functions with checkboxes, then click "Generate Hooks"
- Compile: Click Run > Compile, select your hooks file(s), and build
- Run: Click Run > Run Executable to test your instrumented binary
| Command | Description |
|---|---|
--compile <file> / -c <file> |
Build with hook instrumentation |
--capture |
Capture build commands to build-metadata/go-build.log |
--json |
Capture build with JSON output to build-metadata/ (recommended) |
--callgraph |
Show static call graph |
--pack-functions |
List all functions |
--pack-files |
List compiled files |
- Hooks Reference - Complete hook types and API
- Architecture - Internal design and components
- Go 1.18+
- Linux, macOS, or Windows
Apache License 2.0

