ethereum-optimism / ethereum-optimism/optimism
opgeth-decoupling: own the log layer; re-home the RPC metrics hooks
- Dominant language
- Go
- Stars
- 6.5k
- Forks
- 4k
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 145
Description
Part of #20257. See §15 of the [op-geth decoupling doc](https://github.com/ethereum-optimism/optimism/blob/develop/docs/ai/opgeth-decoupling.md). **Blocks #20266.**
## Problem
Two op-service foundation features are built on op-geth fork extensions to *general-purpose* geth
packages — nothing OP-protocol-specific, so no earlier plan section covers them, but they sit
under every service and break the whole tree at cutover:
1. **Context-based log filtering** — the fork extends `log.Logger` with `SetContext`, `WriteCtx`,
`LogAttrs`, and `Trace/…/ErrorContext`. `op-service/log` (logfilter) builds on it;
`op-service/testlog` implements the whole extended interface.
2. **RPC recording hooks** — the fork adds `rpc.Recorder`/`RecordedMsg`/`RecordDone`/
`WithRecorder` inside the geth RPC client and server. `op-service/metrics` (RPC metrics),
`op-service/rpc` (server handlers), and `op-service/client` (`WithRPCRecorder`) build on it.
(`rpc.JsonError` in op-test-sequencer is the same family; trivially replaced by a local type.)
## Strategy
### (1) Own the log layer — `op-service/log` becomes the monorepo's logging API
Better layering regardless of the decoupling: monorepo code should depend on an internal log
layer, not on `geth/log` directly.
- **Phase 1 (now, mechanical, incremental):** add `oplog.Logger` as a *type alias* of geth
`log.Logger`, plus re-exports of the package-level API in use (`Root`, `SetDefault`,
`NewLogger`, level parsing, …). Sweep all monorepo imports of `go-ethereum/log` to
`op-service/log`. Pure rename while the alias holds — landable per component, zero risk.
- **Phase 2 (at cutover):** flip the alias to an owned interface (upstream's method set + the
context methods) with an slog-backed implementation. Implement over `slog` — do not copy
upstream's LGPL log package; the fork's context-extension logic is OP-authored and ports over.
Because our interface is a superset of upstream's, our loggers still satisfy upstream
`log.Logger` wherever we hand one into geth code (e.g. the in-process L1 geth in op-e2e).
### (2) RPC recorder
- Client side: re-implement recording in our own RPC client wrappers (`op-service/client`) — we
own that seam.
- Server side: the fork hooks observe inside geth's `rpc` server; upstream offers no equivalent.
Needs a small design: HTTP-middleware-level observation, or wrapping the registered handlers.
Metric continuity (names/labels) is required; per-message fidelity may be approximated.
## Acceptance criteria
- No monorepo Go file imports `go-ethereum/log` (grep is the gate).
- RPC metrics keep their metric names/labels on upstream go-ethereum; `rpc.Recorder` &
`rpc.JsonError` uses are gone.
🤖 *Generated by Claude Code*
Contributor guide
Assessment
This issue has not been assessed yet.