perf(metrics): implement plugin chain tracking (#7791)

Remove expensive runtime.Caller calls from metrics Recorder.WriteMsg
by tracking the responding plugin through the plugin chain instead.

- Add PluginTracker interface and pluginWriter wrapper in plugin.go
- Modify NextOrFailure to wrap ResponseWriter with plugin name
- Update metrics Recorder to implement PluginTracker
- Remove authoritativePlugin method using filepath inspection

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
This commit is contained in:
Ville Vesilehto
2025-12-30 00:33:12 +02:00
committed by GitHub
parent b21c752d7f
commit be934b2b06
5 changed files with 263 additions and 25 deletions

View File

@@ -1,8 +1,6 @@
package metrics
import (
"runtime"
"github.com/coredns/coredns/plugin/pkg/dnstest"
"github.com/miekg/dns"
@@ -11,8 +9,9 @@ import (
// Recorder is a dnstest.Recorder specific to the metrics plugin.
type Recorder struct {
*dnstest.Recorder
// CallerN holds the string return value of the call to runtime.Caller(N+1)
Caller [3]string
// Plugin holds the name of the plugin that wrote the response.
// This is set automatically by the plugin chain via the PluginTracker interface.
Plugin string
}
// NewRecorder makes and returns a new Recorder.
@@ -21,8 +20,15 @@ func NewRecorder(w dns.ResponseWriter) *Recorder { return &Recorder{Recorder: dn
// WriteMsg records the status code and calls the
// underlying ResponseWriter's WriteMsg method.
func (r *Recorder) WriteMsg(res *dns.Msg) error {
_, r.Caller[0], _, _ = runtime.Caller(1)
_, r.Caller[1], _, _ = runtime.Caller(2)
_, r.Caller[2], _, _ = runtime.Caller(3)
return r.Recorder.WriteMsg(res)
}
// SetPlugin implements the plugin.PluginTracker interface.
func (r *Recorder) SetPlugin(name string) {
r.Plugin = name
}
// GetPlugin implements the plugin.PluginTracker interface.
func (r *Recorder) GetPlugin() string {
return r.Plugin
}