diff --git a/pkg/symbol/addr2line/go.go b/pkg/symbol/addr2line/go.go index a682244e8ba..8aed4052ca1 100644 --- a/pkg/symbol/addr2line/go.go +++ b/pkg/symbol/addr2line/go.go @@ -19,44 +19,56 @@ import ( "errors" "fmt" + "github.com/go-kit/log" "github.com/google/pprof/profile" ) -func Go(path string) (func(addr uint64) ([]profile.Line, error), error) { +type goLiner struct { + logger log.Logger + + symtab *gosym.Table +} + +func Go(logger log.Logger, path string) (*goLiner, error) { tab, err := gosymtab(path) if err != nil { return nil, fmt.Errorf("failed to create go symbtab: %w", err) } - return func(addr uint64) (lines []profile.Line, err error) { - defer func() { - // PCToLine panics with "invalid memory address or nil pointer dereference", - // - when it refers to an address that doesn't actually exist. - if r := recover(); r != nil { - err = fmt.Errorf("recovering from panic in go binary add2line: %v", r) - } - }() - - file, line, fn := tab.PCToLine(addr) - name := "?" - if fn != nil { - name = fn.Name - } else { - file = "?" - line = 0 + return &goLiner{ + logger: logger, + symtab: tab, + }, nil +} + +func (gl *goLiner) PCToLines(addr uint64) (lines []profile.Line, err error) { + defer func() { + // PCToLine panics with "invalid memory address or nil pointer dereference", + // - when it refers to an address that doesn't actually exist. + if r := recover(); r != nil { + err = fmt.Errorf("recovering from panic in go binary add2line: %v", r) } + }() + + file, line, fn := gl.symtab.PCToLine(addr) + name := "?" + if fn != nil { + name = fn.Name + } else { + file = "?" + line = 0 + } - // TODO(kakkoyun): Find a way to symbolize inline functions. - lines = append(lines, profile.Line{ - Line: int64(line), - Function: &profile.Function{ - Name: name, - Filename: file, - }, - }) + // TODO(kakkoyun): Find a way to symbolize inline functions. + lines = append(lines, profile.Line{ + Line: int64(line), + Function: &profile.Function{ + Name: name, + Filename: file, + }, + }) - return lines, nil - }, nil + return lines, nil } func gosymtab(path string) (*gosym.Table, error) { diff --git a/pkg/symbol/symbol.go b/pkg/symbol/symbol.go index a879fdbcebe..8ba09ca7db4 100644 --- a/pkg/symbol/symbol.go +++ b/pkg/symbol/symbol.go @@ -48,10 +48,6 @@ type liner interface { PCToLines(pc uint64) ([]profile.Line, error) } -type funcLiner func(addr uint64) ([]profile.Line, error) - -func (f funcLiner) PCToLines(pc uint64) ([]profile.Line, error) { return f(pc) } - func NewSymbolizer(logger log.Logger, opts ...Option) (*Symbolizer, error) { log.With(logger, "component", "symbolizer") @@ -104,7 +100,7 @@ func (s *Symbolizer) NewLiner(m *profile.Mapping, path string) (liner, error) { lnr, err := s.newLiner(m, path) if err != nil { s.failed[h] = struct{}{} - s.cache.Invalidate(hash) + s.cache.Invalidate(h) return nil, err } @@ -157,10 +153,10 @@ func (s *Symbolizer) newLiner(m *profile.Mapping, path string) (liner, error) { // Right now, this uses "debug/gosym" package, and it won't work for inlined functions, // so this is just a best-effort implementation, in case we don't have DWARF. level.Debug(s.logger).Log("msg", "symbolizing a Go binary", "file", path) - f, err := addr2line.Go(path) + lnr, err := addr2line.Go(s.logger, path) if err == nil { level.Debug(s.logger).Log("msg", "using go liner to resolve symbols", "file", path) - return funcLiner(f), nil + return lnr, nil } level.Error(s.logger).Log( "msg", "failed to create go liner, falling back to binary liner",