mirror of https://github.com/tgragnato/magnetico
feat(stats): add pyroscope profiling support
This commit is contained in:
parent
78f6538902
commit
5d261e12df
2
go.mod
2
go.mod
|
|
@ -5,6 +5,7 @@ go 1.22.6
|
|||
require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/bits-and-blooms/bloom/v3 v3.7.0
|
||||
github.com/grafana/pyroscope-go v1.2.0
|
||||
github.com/jackc/pgx/v5 v5.7.2
|
||||
github.com/jessevdk/go-flags v1.6.1
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
|
|
@ -22,6 +23,7 @@ require (
|
|||
github.com/bits-and-blooms/bitset v1.20.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -15,6 +15,10 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
|||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/grafana/pyroscope-go v1.2.0 h1:aILLKjTj8CS8f/24OPMGPewQSYlhmdQMBmol1d3KGj8=
|
||||
github.com/grafana/pyroscope-go v1.2.0/go.mod h1:2GHr28Nr05bg2pElS+dDsc98f3JTUh2f6Fz1hWXrqwk=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
|
|
@ -66,6 +70,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj
|
|||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
|
|
|
|||
8
main.go
8
main.go
|
|
@ -44,6 +44,14 @@ func main() {
|
|||
}
|
||||
}()
|
||||
|
||||
if opFlags.PyroscopeURL != "" {
|
||||
profiler, err := stats.InitPyroscope(opFlags.PyroscopeURL)
|
||||
if err != nil {
|
||||
log.Fatalf("could not start pyroscope %s\n", err.Error())
|
||||
}
|
||||
defer profiler.Stop()
|
||||
}
|
||||
|
||||
database, err := persistence.MakeDatabase(opFlags.DatabaseURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not open the database %s. %s\n", opFlags.DatabaseURL, err.Error())
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import (
|
|||
)
|
||||
|
||||
type OpFlags struct {
|
||||
DatabaseURL string `long:"database" description:"URL of the database." default:"postgres://magnetico:magnetico@localhost:5432/magnetico?sslmode=disable" yaml:"databaseURL"`
|
||||
DatabaseURL string `long:"database" description:"URL of the database." default:"postgres://magnetico:magnetico@localhost:5432/magnetico?sslmode=disable" yaml:"databaseURL"`
|
||||
PyroscopeURL string `long:"pyroscope" description:"URL of the Pyroscope server." default:"" yaml:"pyroscopeURL"`
|
||||
|
||||
IndexerAddrs []string `long:"indexer-addr" description:"Address(es) to be used by indexing DHT nodes." default:"0.0.0.0:0" yaml:"indexerAddrs"`
|
||||
IndexerMaxNeighbors uint `long:"indexer-max-neighbors" description:"Maximum number of neighbors of an indexer." default:"5000" yaml:"indexerMaxNeighbors"`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
package stats
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/grafana/pyroscope-go"
|
||||
)
|
||||
|
||||
func InitPyroscope(serverAddress string) (*pyroscope.Profiler, error) {
|
||||
if serverAddress == "" {
|
||||
return nil, errors.New("pyroscope server address is required")
|
||||
}
|
||||
|
||||
runtime.SetMutexProfileFraction(5)
|
||||
runtime.SetBlockProfileRate(5)
|
||||
|
||||
return pyroscope.Start(pyroscope.Config{
|
||||
ApplicationName: "magnetico.tgragnato.it",
|
||||
ServerAddress: serverAddress,
|
||||
Logger: nil,
|
||||
Tags: map[string]string{"hostname": os.Getenv("HOSTNAME")},
|
||||
ProfileTypes: []pyroscope.ProfileType{
|
||||
pyroscope.ProfileCPU,
|
||||
pyroscope.ProfileAllocObjects,
|
||||
pyroscope.ProfileAllocSpace,
|
||||
pyroscope.ProfileInuseObjects,
|
||||
pyroscope.ProfileInuseSpace,
|
||||
pyroscope.ProfileGoroutines,
|
||||
pyroscope.ProfileMutexCount,
|
||||
pyroscope.ProfileMutexDuration,
|
||||
pyroscope.ProfileBlockCount,
|
||||
pyroscope.ProfileBlockDuration,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package stats
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInitPyroscope(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
serverAddr string
|
||||
wantErr bool
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "Valid server address",
|
||||
serverAddr: "http://localhost:4040",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Empty server address",
|
||||
serverAddr: "",
|
||||
wantErr: true,
|
||||
expectedError: "pyroscope server address is required",
|
||||
},
|
||||
}
|
||||
|
||||
origHostname := os.Getenv("HOSTNAME")
|
||||
os.Setenv("HOSTNAME", "test-host")
|
||||
defer os.Setenv("HOSTNAME", origHostname)
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
profiler, err := InitPyroscope(tt.serverAddr)
|
||||
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Error("expected error but got none")
|
||||
}
|
||||
if err != nil && err.Error() != tt.expectedError {
|
||||
t.Errorf("expected error %v, got %v", tt.expectedError, err.Error())
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if profiler == nil {
|
||||
t.Error("expected non-nil profiler")
|
||||
}
|
||||
}
|
||||
|
||||
if profiler != nil {
|
||||
profiler.Stop()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue