Compare commits

...

2 Commits

Author SHA1 Message Date
grandwizard28
f0bfdbc4e2 refactor(pprof): remove redundant exports 2026-03-23 00:44:02 +05:30
grandwizard28
9a284a3cbe refactor(pprof): extract infrastructure provider 2026-03-23 00:41:02 +05:30
12 changed files with 209 additions and 21 deletions

View File

@@ -39,6 +39,13 @@ instrumentation:
host: "0.0.0.0"
port: 9090
##################### PProf #####################
pprof:
# Whether to enable the pprof server.
enabled: true
# The address on which the pprof server listens.
address: 0.0.0.0:6060
##################### Web #####################
web:
# Whether to enable the web frontend

View File

@@ -5,7 +5,6 @@ import (
"fmt"
"net"
"net/http"
_ "net/http/pprof" // http profiler
"slices"
"go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux"
@@ -313,15 +312,6 @@ func (s *Server) Start(ctx context.Context) error {
s.unavailableChannel <- healthcheck.Unavailable
}()
go func() {
slog.Info("Starting pprof server", "addr", baseconst.DebugHttpPort)
err = http.ListenAndServe(baseconst.DebugHttpPort, nil)
if err != nil {
slog.Error("Could not start pprof server", errors.Attr(err))
}
}()
go func() {
slog.Info("Starting OpAmp Websocket server", "addr", baseconst.OpAmpWsEndpoint)
err := s.opampServer.Start(baseconst.OpAmpWsEndpoint)

32
pkg/pprof/config.go Normal file
View File

@@ -0,0 +1,32 @@
package pprof
import "github.com/SigNoz/signoz/pkg/factory"
// Config holds the configuration for the pprof server.
type Config struct {
Enabled bool `mapstructure:"enabled"`
Address string `mapstructure:"address"`
}
func NewConfigFactory() factory.ConfigFactory {
return factory.NewConfigFactory(factory.MustNewName("pprof"), newConfig)
}
func newConfig() factory.Config {
return Config{
Enabled: true,
Address: "0.0.0.0:6060",
}
}
func (c Config) Validate() error {
return nil
}
func (c Config) Provider() string {
if c.Enabled {
return "http"
}
return "noop"
}

42
pkg/pprof/config_test.go Normal file
View File

@@ -0,0 +1,42 @@
package pprof
import (
"context"
"testing"
"github.com/SigNoz/signoz/pkg/config"
"github.com/SigNoz/signoz/pkg/config/envprovider"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewWithEnvProvider(t *testing.T) {
t.Setenv("SIGNOZ_PPROF_ENABLED", "false")
t.Setenv("SIGNOZ_PPROF_ADDRESS", "127.0.0.1:6061")
conf, err := config.New(
context.Background(),
config.ResolverConfig{
Uris: []string{"env:"},
ProviderFactories: []config.ProviderFactory{
envprovider.NewFactory(),
},
},
[]factory.ConfigFactory{
NewConfigFactory(),
},
)
require.NoError(t, err)
actual := Config{}
err = conf.Unmarshal("pprof", &actual)
require.NoError(t, err)
expected := Config{
Enabled: false,
Address: "127.0.0.1:6061",
}
assert.Equal(t, expected, actual)
}

View File

@@ -0,0 +1,58 @@
package httppprof
import (
"context"
"log/slog"
"net/http"
httppprof "net/http/pprof"
runtimepprof "runtime/pprof"
"github.com/SigNoz/signoz/pkg/factory"
httpserver "github.com/SigNoz/signoz/pkg/http/server"
"github.com/SigNoz/signoz/pkg/pprof"
)
type provider struct {
server *httpserver.Server
}
func NewFactory() factory.ProviderFactory[pprof.PProf, pprof.Config] {
return factory.NewProviderFactory(factory.MustNewName("http"), New)
}
func New(_ context.Context, settings factory.ProviderSettings, config pprof.Config) (pprof.PProf, error) {
server, err := httpserver.New(
settings.Logger.With(slog.String("pkg", "github.com/SigNoz/signoz/pkg/pprof/httppprof")),
httpserver.Config{Address: config.Address},
newHandler(),
)
if err != nil {
return nil, err
}
return &provider{server: server}, nil
}
func (provider *provider) Start(ctx context.Context) error {
return provider.server.Start(ctx)
}
func (provider *provider) Stop(ctx context.Context) error {
return provider.server.Stop(ctx)
}
func newHandler() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/debug/pprof/", httppprof.Index)
mux.HandleFunc("/debug/pprof/cmdline", httppprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", httppprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", httppprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", httppprof.Trace)
// Register the runtime profiles in the same order returned by runtime/pprof.Profiles().
for _, profile := range runtimepprof.Profiles() {
mux.Handle("/debug/pprof/"+profile.Name(), httppprof.Handler(profile.Name()))
}
return mux
}

View File

@@ -0,0 +1,35 @@
package nooppprof
import (
"context"
"sync"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/pprof"
)
type provider struct {
stopC chan struct{}
stopOnce sync.Once
}
func NewFactory() factory.ProviderFactory[pprof.PProf, pprof.Config] {
return factory.NewProviderFactory(factory.MustNewName("noop"), New)
}
func New(_ context.Context, _ factory.ProviderSettings, _ pprof.Config) (pprof.PProf, error) {
return &provider{stopC: make(chan struct{})}, nil
}
func (provider *provider) Start(context.Context) error {
<-provider.stopC
return nil
}
func (provider *provider) Stop(context.Context) error {
provider.stopOnce.Do(func() {
close(provider.stopC)
})
return nil
}

8
pkg/pprof/pprof.go Normal file
View File

@@ -0,0 +1,8 @@
package pprof
import "github.com/SigNoz/signoz/pkg/factory"
// PProf is the interface that wraps the pprof service lifecycle.
type PProf interface {
factory.Service
}

View File

@@ -5,7 +5,6 @@ import (
"fmt"
"net"
"net/http"
_ "net/http/pprof" // http profiler
"slices"
"github.com/SigNoz/signoz/pkg/cache/memorycache"
@@ -294,15 +293,6 @@ func (s *Server) Start(ctx context.Context) error {
s.unavailableChannel <- healthcheck.Unavailable
}()
go func() {
slog.Info("Starting pprof server", "addr", constants.DebugHttpPort)
err = http.ListenAndServe(constants.DebugHttpPort, nil)
if err != nil {
slog.Error("Could not start pprof server", errors.Attr(err))
}
}()
go func() {
slog.Info("Starting OpAmp Websocket server", "addr", constants.OpAmpWsEndpoint)
err := s.opampServer.Start(constants.OpAmpWsEndpoint)

View File

@@ -14,7 +14,6 @@ import (
const (
HTTPHostPort = "0.0.0.0:8080" // Address to serve http (query service)
PrivateHostPort = "0.0.0.0:8085" // Address to server internal services like alert manager
DebugHttpPort = "0.0.0.0:6060" // Address to serve http (pprof)
OpAmpWsEndpoint = "0.0.0.0:4320" // address for opamp websocket
)

View File

@@ -23,6 +23,7 @@ import (
"github.com/SigNoz/signoz/pkg/instrumentation"
"github.com/SigNoz/signoz/pkg/modules/metricsexplorer"
"github.com/SigNoz/signoz/pkg/modules/user"
"github.com/SigNoz/signoz/pkg/pprof"
"github.com/SigNoz/signoz/pkg/prometheus"
"github.com/SigNoz/signoz/pkg/querier"
"github.com/SigNoz/signoz/pkg/ruler"
@@ -50,6 +51,9 @@ type Config struct {
// Instrumentation config
Instrumentation instrumentation.Config `mapstructure:"instrumentation"`
// PProf config
PProf pprof.Config `mapstructure:"pprof"`
// Analytics config
Analytics analytics.Config `mapstructure:"analytics"`
@@ -122,6 +126,7 @@ func NewConfig(ctx context.Context, logger *slog.Logger, resolverConfig config.R
global.NewConfigFactory(),
version.NewConfigFactory(),
instrumentation.NewConfigFactory(),
pprof.NewConfigFactory(),
analytics.NewConfigFactory(),
web.NewConfigFactory(),
cache.NewConfigFactory(),

View File

@@ -34,6 +34,9 @@ import (
"github.com/SigNoz/signoz/pkg/modules/session/implsession"
"github.com/SigNoz/signoz/pkg/modules/user"
"github.com/SigNoz/signoz/pkg/modules/user/impluser"
"github.com/SigNoz/signoz/pkg/pprof"
"github.com/SigNoz/signoz/pkg/pprof/httppprof"
"github.com/SigNoz/signoz/pkg/pprof/nooppprof"
"github.com/SigNoz/signoz/pkg/prometheus"
"github.com/SigNoz/signoz/pkg/prometheus/clickhouseprometheus"
"github.com/SigNoz/signoz/pkg/querier"
@@ -89,6 +92,13 @@ func NewWebProviderFactories() factory.NamedMap[factory.ProviderFactory[web.Web,
)
}
func NewPProfProviderFactories() factory.NamedMap[factory.ProviderFactory[pprof.PProf, pprof.Config]] {
return factory.MustNewNamedMap(
httppprof.NewFactory(),
nooppprof.NewFactory(),
)
}
func NewSQLStoreProviderFactories() factory.NamedMap[factory.ProviderFactory[sqlstore.SQLStore, sqlstore.Config]] {
return factory.MustNewNamedMap(
sqlitesqlstore.NewFactory(sqlstorehook.NewLoggingFactory(), sqlstorehook.NewInstrumentationFactory()),

View File

@@ -107,6 +107,17 @@ func New(
// Get the provider settings from instrumentation
providerSettings := instrumentation.ToProviderSettings()
pprofService, err := factory.NewProviderFromNamedMap(
ctx,
providerSettings,
config.PProf,
NewPProfProviderFactories(),
config.PProf.Provider(),
)
if err != nil {
return nil, err
}
// Initialize analytics just after instrumentation, as providers might require it
analytics, err := factory.NewProviderFromNamedMap(
ctx,
@@ -448,6 +459,7 @@ func New(
registry, err := factory.NewRegistry(
instrumentation.Logger(),
factory.NewNamedService(factory.MustNewName("instrumentation"), instrumentation),
factory.NewNamedService(factory.MustNewName("pprof"), pprofService),
factory.NewNamedService(factory.MustNewName("analytics"), analytics),
factory.NewNamedService(factory.MustNewName("alertmanager"), alertmanager),
factory.NewNamedService(factory.MustNewName("licensing"), licensing),