diff --git a/cmd/api/main.go b/cmd/api/main.go index 402e70dc7..f3b7c4bac 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" "os" + "runtime" "time" "github.com/baking-bad/bcdhub/cmd/api/handlers" @@ -20,6 +21,7 @@ import ( "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/go-playground/validator/v10" + "github.com/pyroscope-io/client/pyroscope" ) type app struct { @@ -27,8 +29,9 @@ type app struct { Contexts config.Contexts Config config.Config - cancel context.CancelFunc - worker *periodic.GeneralWorker + cancel context.CancelFunc + worker *periodic.GeneralWorker + profiler *pyroscope.Profiler } func newApp() *app { @@ -46,6 +49,38 @@ func newApp() *app { app := new(app) app.Config = cfg + runtime.SetMutexProfileFraction(5) + runtime.SetBlockProfileRate(5) + + if cfg.Profiler != nil { + profiler, err := pyroscope.Start(pyroscope.Config{ + ApplicationName: "bcdhub.api", + ServerAddress: cfg.Profiler.Server, + Tags: map[string]string{ + "hostname": os.Getenv("BCDHUB_SERVICE"), + "project": "bcdhub", + "service": "api", + }, + + ProfileTypes: []pyroscope.ProfileType{ + pyroscope.ProfileCPU, + pyroscope.ProfileAllocObjects, + pyroscope.ProfileAllocSpace, + pyroscope.ProfileInuseObjects, + pyroscope.ProfileInuseSpace, + pyroscope.ProfileGoroutines, + pyroscope.ProfileMutexCount, + pyroscope.ProfileMutexDuration, + pyroscope.ProfileBlockCount, + pyroscope.ProfileBlockDuration, + }, + }) + if err != nil { + panic(err) + } + app.profiler = profiler + } + if cfg.API.Periodic != nil { worker, err := periodic.NewGeneralWorker(*cfg.API.Periodic, app.handleUrlChanged) if err != nil { @@ -229,6 +264,12 @@ func (api *app) makeRouter() { func (api *app) Close() error { api.cancel() + if api.profiler != nil { + if err := api.profiler.Stop(); err != nil { + return err + } + } + if err := api.Contexts.Close(); err != nil { return err } diff --git a/cmd/indexer/main.go b/cmd/indexer/main.go index d5dd3eee5..f01a02a4a 100644 --- a/cmd/indexer/main.go +++ b/cmd/indexer/main.go @@ -11,6 +11,7 @@ import ( "github.com/baking-bad/bcdhub/internal/config" "github.com/baking-bad/bcdhub/internal/helpers" "github.com/baking-bad/bcdhub/internal/logger" + "github.com/pyroscope-io/client/pyroscope" ) func main() { @@ -26,6 +27,35 @@ func main() { defer helpers.CatchPanicSentry() } + var profiler *pyroscope.Profiler + if cfg.Profiler != nil { + profiler, err = pyroscope.Start(pyroscope.Config{ + ApplicationName: "bcdhub.indexer", + ServerAddress: cfg.Profiler.Server, + Tags: map[string]string{ + "hostname": os.Getenv("BCDHUB_SERVICE"), + "project": "bcdhub", + "service": "indexer", + }, + + ProfileTypes: []pyroscope.ProfileType{ + pyroscope.ProfileCPU, + pyroscope.ProfileAllocObjects, + pyroscope.ProfileAllocSpace, + pyroscope.ProfileInuseObjects, + pyroscope.ProfileInuseSpace, + pyroscope.ProfileGoroutines, + pyroscope.ProfileMutexCount, + pyroscope.ProfileMutexDuration, + pyroscope.ProfileBlockCount, + pyroscope.ProfileBlockDuration, + }, + }) + if err != nil { + panic(err) + } + } + var wg sync.WaitGroup ctx, cancel := context.WithCancel(context.Background()) @@ -54,5 +84,11 @@ func main() { panic(err) } } + + if profiler != nil { + if err := profiler.Stop(); err != nil { + panic(err) + } + } logger.Info().Msg("Stopped") } diff --git a/configs/production.yml b/configs/production.yml index dd5eec275..a08013879 100644 --- a/configs/production.yml +++ b/configs/production.yml @@ -52,6 +52,9 @@ share_path: /etc/bcd base_url: https://better-call.dev +profiler: + server: ${PROFILER_SERVER_ADDRESS:-http://127.0.0.1:4040} + api: project_name: api bind: ":14000" diff --git a/go.mod b/go.mod index 51194bafa..61a2375f9 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/baking-bad/bcdhub -go 1.19 +go 1.20 require ( github.com/aws/aws-sdk-go v1.44.92 @@ -25,6 +25,7 @@ require ( github.com/machinebox/graphql v0.2.2 github.com/microcosm-cc/bluemonday v1.0.20 github.com/pkg/errors v0.9.1 + github.com/pyroscope-io/client v0.7.2 github.com/robfig/cron/v3 v3.0.1 github.com/rs/zerolog v1.28.0 github.com/schollz/progressbar/v3 v3.10.1 @@ -33,7 +34,7 @@ require ( github.com/stretchr/testify v1.8.3 github.com/tidwall/gjson v1.14.3 github.com/yhirose/go-peg v0.0.0-20210804202551-de25d6753cf1 - golang.org/x/crypto v0.9.0 + golang.org/x/crypto v0.12.0 golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 gopkg.in/yaml.v3 v3.0.1 ) @@ -76,6 +77,7 @@ require ( github.com/onsi/gomega v1.20.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pyroscope-io/godeltaprof v0.1.2 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect @@ -89,10 +91,10 @@ require ( github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.10.0 // indirect + golang.org/x/net v0.14.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/term v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect google.golang.org/protobuf v1.30.0 // indirect lukechampine.com/blake3 v1.1.6 // indirect mellium.im/sasl v0.3.1 // indirect diff --git a/go.sum b/go.sum index 55751557e..f8da635fc 100644 --- a/go.sum +++ b/go.sum @@ -209,6 +209,10 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/pyroscope-io/client v0.7.2 h1:OX2qdUQsS8RSkn/3C8isD7f/P0YiZQlRbAlecAaj/R8= +github.com/pyroscope-io/client v0.7.2/go.mod h1:FEocnjn+Ngzxy6EtU9ZxXWRvQ0+pffkrBxHLnPpxwi8= +github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4= +github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= @@ -282,8 +286,8 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -301,8 +305,8 @@ golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -334,20 +338,20 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/internal/config/config.go b/internal/config/config.go index 2426d6434..785026d81 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -27,6 +27,7 @@ type Config struct { Sentry SentryConfig `yaml:"sentry"` SharePath string `yaml:"share_path"` BaseURL string `yaml:"base_url"` + Profiler *Profiler `yaml:"profiler"` API APIConfig `yaml:"api"` @@ -44,6 +45,11 @@ type Config struct { } `yaml:"scripts"` } +// Profiler - +type Profiler struct { + Server string `yaml:"server"` +} + // IndexerConfig - type IndexerConfig struct { ReceiverThreads int64 `yaml:"receiver_threads"`