Skip to content

Commit acdfae7

Browse files
committed
docs: add AGENTS.md codebase map; document remaining config fields
- AGENTS.md: orientation map for AI agents/new contributors — module layout, file-by-file responsibilities, the three core flows (config resolution, Init pipeline, endpoint/path resolution), conventions, and where to find things - config.go: doc comments on the selfTest/dryRun fields
1 parent 141b7ea commit acdfae7

2 files changed

Lines changed: 75 additions & 2 deletions

File tree

AGENTS.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# AGENTS.md — codebase map for AI agents
2+
3+
Read this first. It is the orientation map for `ubgo/otelkit` so a fresh agent (or human) knows what every part does, how the pieces connect, and where to make a change — without reading every file.
4+
5+
## What this repo is
6+
7+
`otelkit` is an **OpenTelemetry bootstrap for Go**: one constructor (`Init`) that stands up the trace/metric/log SDK pipeline (providers + exporters + resource + propagators + ordered shutdown) and points it at a backend. It is a *bootstrap, not an SDK* — it wires `go.opentelemetry.io/otel`, never reimplements it. It does **not** write log lines (that's a logger's job) and does **not** do auto-instrumentation. See `README.md` for the user-facing pitch and `docs/architecture.md` for the design.
8+
9+
## Modules (multi-module repo)
10+
11+
| Path | Module | Role |
12+
|---|---|---|
13+
| `.` | `github.com/ubgo/otelkit` | Core: everything except gRPC. Deps: stdlib + `otel/*` + `otelconf` + `autoexport`. |
14+
| `contrib/otelkit-grpc/` | `…/contrib/otelkit-grpc` | OTLP/gRPC exporters. Self-registers via `otelkit.RegisterGRPC` on blank import. Keeps `google.golang.org/grpc` out of the core. |
15+
| `examples/` | `…/examples` | 8 runnable programs. Replaces the two above to `../`. Must compile in CI. |
16+
17+
`go.work` is a **local-dev convenience only and is gitignored** — CI builds each module standalone (each has its own `go.mod`, the examples/contrib use `replace` to the local core). Minimum Go: **1.25** (pulled up by `otelconf`).
18+
19+
## Core files — what each owns
20+
21+
| File | Responsibility |
22+
|---|---|
23+
| `doc.go` | Package overview godoc. |
24+
| `types.go` | The enums: `Signal`, `Transport`, `Sampler`, `Temporality`, `TLSMode` + their OTEL-spec mappings (ports 4317/4318, `/v1/<signal>` suffixes, protocol/sampler value strings). |
25+
| `errors.go` | Exported sentinel errors (`ErrMissingEndpoint`, `ErrGRPCNotLinked`, …). |
26+
| `config.go` | `Config` + `SignalConfig` + defaults, **and** `resolveEndpoint`/`GRPCTarget` — the pure port+path resolver (the footgun-killer). |
27+
| `env.go` | The `OTEL_*` environment overlay (`applyEnv`) + parse helpers. The only file that reads `os.Getenv`. |
28+
| `options.go` | The public `With*` functional options + the `Option` type. |
29+
| `resource.go` | Builds the OTEL `Resource` (detectors, `unknown_service` fallback, `deployment.environment.name`). |
30+
| `exporters.go` | Per-signal OTLP/HTTP + stdout exporter construction; the gRPC factory seam + `RegisterGRPC`. |
31+
| `providers.go` | Builds the Tracer/Meter/Logger providers (+ sampler, no-op providers for disabled signals). |
32+
| `otelkit.go` | **The entry point**: `Init`, the `*Telemetry` handle, accessors, `SetGlobal`, `ForceFlush`, `SelfTest`, the propagator builder, and the dry-run printer. |
33+
| `shutdown.go` | `Shutdown` (ordered logs→metrics→traces, `errors.Join`) + `RunOnSignal`. |
34+
| `errhandler.go` | Installs the global OTEL error handler (loud-by-default). |
35+
| `probe.go` | `ProbeEndpoint` — the connectivity diagnostic. |
36+
| `presets.go` | Vendor presets (`PresetHyperDX`, …) + `Preset`/`WithPreset`. |
37+
| `declarative.go` | `OTEL_CONFIG_FILE` delegation to `otelconf`. |
38+
39+
Every file starts with a header comment describing its role; every exported symbol has godoc.
40+
41+
## The three flows to understand
42+
43+
1. **Config resolution** (`otelkit.go:Init``options.go``env.go` / `declarative.go`): start from `defaultConfig()`, apply preset+options, then either delegate to a config file (`OTEL_CONFIG_FILE`) or overlay `OTEL_*` env. Precedence: **defaults < preset < options < env**; a config file wins outright.
44+
2. **The Init pipeline** (`otelkit.go:Init`): resolve config → `buildResource``buildTracerProvider`/`buildMeterProvider`/`buildLoggerProvider` (each builds an exporter via `exporters.go`) → install error handler → assemble `*Telemetry` → optional self-test. `OTEL_SDK_DISABLED` short-circuits to a no-op handle.
45+
3. **Endpoint/path resolution** (`config.go:resolveEndpoint`): the single place that turns a host/URL + transport into the correct dial target — gRPC `host:port` (4317), HTTP with the `/v1/<signal>` append rule (and double-append guard), per-signal URLs verbatim. This is the most-tested logic; if you touch OTLP endpoints, this is the file.
46+
47+
## Conventions (also in CONTRIBUTING.md)
48+
49+
- **100% line coverage, `-race`, enforced in CI.** `task cover` fails under 100%. Cover error branches with small test seams (e.g. `buildResourceFn`, `newSDKFn`) rather than leaving them uncovered.
50+
- **Lean core deps.** Anything heavy (notably gRPC) goes in a `contrib/` module behind the factory seam.
51+
- **No `init()` magic; pure constructors.** Globals are opt-in via `SetGlobal`.
52+
- **Loud, not silent.** New failure modes surface as an error or logged warning.
53+
- **Comments explain *why*, not *what*** — the names carry the *what*.
54+
55+
## Running things
56+
57+
```sh
58+
task cover # core: race + 100% gate
59+
cd contrib/otelkit-grpc && go test -race ./...
60+
cd examples && go build ./...
61+
```
62+
63+
## Where to look for X
64+
65+
- "How do I configure it?" → `docs/configuration.md` (env vars) + `options.go`.
66+
- "Add a vendor" → `presets.go` + `docs/presets.md`; assert the exact endpoint/auth/temporality in `presets_test.go`.
67+
- "Why isn't data arriving?" → `probe.go`, `errhandler.go`, the dry-run in `otelkit.go`, and `docs/diagnostics.md`.
68+
- "Add gRPC behavior" → `contrib/otelkit-grpc/grpc.go`.
69+
- "The design rationale" → `docs/adr/` (Architecture Decision Records).

config.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,12 @@ type Config struct {
6969
// envOverrides, when false, makes programmatic/preset values win over raw
7070
// OTEL_* environment variables. Default true (spec precedence).
7171
envOverrides bool
72-
selfTest bool
73-
dryRun bool
72+
// selfTest, set by WithSelfTest, makes Init send one span synchronously and
73+
// fail loudly if it can't be exported.
74+
selfTest bool
75+
// dryRun, set by WithDryRun, prints the resolved config and exports to
76+
// stdout instead of the configured backend.
77+
dryRun bool
7478
}
7579

7680
// SignalConfig configures one signal's exporter. A disabled signal yields a

0 commit comments

Comments
 (0)