Compare commits
39 Commits
v0.75.0-pa
...
injection
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
060edb8492 | ||
|
|
43414275b5 | ||
|
|
66a0830dc7 | ||
|
|
ba749a12ad | ||
|
|
b59744a4e0 | ||
|
|
fbfc2d3626 | ||
|
|
fb1157515d | ||
|
|
8e7ede0642 | ||
|
|
4a068eb68c | ||
|
|
0aba107436 | ||
|
|
e99d3427ec | ||
|
|
44cbe53705 | ||
|
|
1ccc0b3c48 | ||
|
|
e695f89c85 | ||
|
|
f080bcd3ee | ||
|
|
a5635b10e1 | ||
|
|
1ab9018641 | ||
|
|
c3153012a6 | ||
|
|
8ba479d3bb | ||
|
|
4d398b1bb1 | ||
|
|
8874da0cf6 | ||
|
|
756c9d7364 | ||
|
|
f48a919945 | ||
|
|
f0b58cd5ae | ||
|
|
3095db106b | ||
|
|
0f06ea1a0c | ||
|
|
188d8a4302 | ||
|
|
db95840260 | ||
|
|
c0bf5f5b0a | ||
|
|
35ecd38cef | ||
|
|
6bd1e1387c | ||
|
|
6680622762 | ||
|
|
f3f315726d | ||
|
|
513629e02d | ||
|
|
b180999a71 | ||
|
|
040c0d708b | ||
|
|
64c62896f8 | ||
|
|
a1160b990d | ||
|
|
79d99f21f8 |
@@ -82,7 +82,6 @@ type ServerOptions struct {
|
|||||||
GatewayUrl string
|
GatewayUrl string
|
||||||
UseLogsNewSchema bool
|
UseLogsNewSchema bool
|
||||||
UseTraceNewSchema bool
|
UseTraceNewSchema bool
|
||||||
SkipWebFrontend bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server runs HTTP api service
|
// Server runs HTTP api service
|
||||||
@@ -396,11 +395,9 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler, web web.Web) (*h
|
|||||||
|
|
||||||
handler = handlers.CompressHandler(handler)
|
handler = handlers.CompressHandler(handler)
|
||||||
|
|
||||||
if !s.serverOptions.SkipWebFrontend {
|
err := web.AddToRouter(r)
|
||||||
err := web.AddToRouter(r)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &http.Server{
|
return &http.Server{
|
||||||
|
|||||||
@@ -10,17 +10,24 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.opentelemetry.io/collector/confmap"
|
|
||||||
"go.opentelemetry.io/otel/sdk/resource"
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
||||||
"go.signoz.io/signoz/ee/query-service/app"
|
"go.signoz.io/signoz/ee/query-service/app"
|
||||||
signozconfig "go.signoz.io/signoz/pkg/config"
|
"go.signoz.io/signoz/pkg/cache/memorycache"
|
||||||
"go.signoz.io/signoz/pkg/confmap/provider/signozenvprovider"
|
"go.signoz.io/signoz/pkg/cache/rediscache"
|
||||||
|
"go.signoz.io/signoz/pkg/config"
|
||||||
|
"go.signoz.io/signoz/pkg/config/envprovider"
|
||||||
|
"go.signoz.io/signoz/pkg/config/fileprovider"
|
||||||
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/query-service/auth"
|
"go.signoz.io/signoz/pkg/query-service/auth"
|
||||||
baseconst "go.signoz.io/signoz/pkg/query-service/constants"
|
baseconst "go.signoz.io/signoz/pkg/query-service/constants"
|
||||||
"go.signoz.io/signoz/pkg/query-service/migrate"
|
"go.signoz.io/signoz/pkg/query-service/migrate"
|
||||||
"go.signoz.io/signoz/pkg/query-service/version"
|
"go.signoz.io/signoz/pkg/query-service/version"
|
||||||
"go.signoz.io/signoz/pkg/signoz"
|
"go.signoz.io/signoz/pkg/signoz"
|
||||||
|
"go.signoz.io/signoz/pkg/sqlmigration"
|
||||||
|
"go.signoz.io/signoz/pkg/sqlstore/sqlitesqlstore"
|
||||||
|
"go.signoz.io/signoz/pkg/web/noopweb"
|
||||||
|
"go.signoz.io/signoz/pkg/web/routerweb"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
|
||||||
@@ -108,7 +115,6 @@ func main() {
|
|||||||
var dialTimeout time.Duration
|
var dialTimeout time.Duration
|
||||||
var gatewayUrl string
|
var gatewayUrl string
|
||||||
var useLicensesV3 bool
|
var useLicensesV3 bool
|
||||||
var skipWebFrontend bool
|
|
||||||
|
|
||||||
flag.BoolVar(&useLogsNewSchema, "use-logs-new-schema", false, "use logs_v2 schema for logs")
|
flag.BoolVar(&useLogsNewSchema, "use-logs-new-schema", false, "use logs_v2 schema for logs")
|
||||||
flag.BoolVar(&useTraceNewSchema, "use-trace-new-schema", false, "use new schema for traces")
|
flag.BoolVar(&useTraceNewSchema, "use-trace-new-schema", false, "use new schema for traces")
|
||||||
@@ -126,7 +132,6 @@ func main() {
|
|||||||
flag.StringVar(&cluster, "cluster", "cluster", "(cluster name - defaults to 'cluster')")
|
flag.StringVar(&cluster, "cluster", "cluster", "(cluster name - defaults to 'cluster')")
|
||||||
flag.StringVar(&gatewayUrl, "gateway-url", "", "(url to the gateway)")
|
flag.StringVar(&gatewayUrl, "gateway-url", "", "(url to the gateway)")
|
||||||
flag.BoolVar(&useLicensesV3, "use-licenses-v3", false, "use licenses_v3 schema for licenses")
|
flag.BoolVar(&useLicensesV3, "use-licenses-v3", false, "use licenses_v3 schema for licenses")
|
||||||
flag.BoolVar(&skipWebFrontend, "skip-web-frontend", false, "skip web frontend")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
loggerMgr := initZapLog(enableQueryServiceLogOTLPExport)
|
loggerMgr := initZapLog(enableQueryServiceLogOTLPExport)
|
||||||
@@ -136,19 +141,40 @@ func main() {
|
|||||||
|
|
||||||
version.PrintVersion()
|
version.PrintVersion()
|
||||||
|
|
||||||
config, err := signozconfig.New(context.Background(), signozconfig.ProviderSettings{
|
config, err := signoz.NewConfig(context.Background(), config.ResolverConfig{
|
||||||
ResolverSettings: confmap.ResolverSettings{
|
Uris: []string{"env:"},
|
||||||
URIs: []string{"signozenv:"},
|
ProviderFactories: []config.ProviderFactory{
|
||||||
ProviderFactories: []confmap.ProviderFactory{
|
envprovider.NewFactory(),
|
||||||
signozenvprovider.NewFactory(),
|
fileprovider.NewFactory(),
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.L().Fatal("Failed to create config", zap.Error(err))
|
zap.L().Fatal("Failed to create config", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
signoz, err := signoz.New(config, skipWebFrontend)
|
signoz, err := signoz.New(context.Background(), config, signoz.ProviderConfig{
|
||||||
|
CacheProviderFactories: factory.MustNewNamedMap(
|
||||||
|
memorycache.NewFactory(),
|
||||||
|
rediscache.NewFactory(),
|
||||||
|
),
|
||||||
|
WebProviderFactories: factory.MustNewNamedMap(
|
||||||
|
routerweb.NewFactory(),
|
||||||
|
noopweb.NewFactory(),
|
||||||
|
),
|
||||||
|
SQLStoreProviderFactories: factory.MustNewNamedMap(
|
||||||
|
sqlitesqlstore.NewFactory(),
|
||||||
|
),
|
||||||
|
SQLMigrationProviderFactories: factory.MustNewNamedMap(
|
||||||
|
sqlmigration.NewAddDataMigrationsFactory(),
|
||||||
|
sqlmigration.NewAddOrganizationFactory(),
|
||||||
|
sqlmigration.NewAddPreferencesFactory(),
|
||||||
|
sqlmigration.NewAddDashboardsFactory(),
|
||||||
|
sqlmigration.NewAddSavedViewsFactory(),
|
||||||
|
sqlmigration.NewAddAgentsFactory(),
|
||||||
|
sqlmigration.NewAddPipelinesFactory(),
|
||||||
|
sqlmigration.NewAddIntegrationsFactory(),
|
||||||
|
),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.L().Fatal("Failed to create signoz struct", zap.Error(err))
|
zap.L().Fatal("Failed to create signoz struct", zap.Error(err))
|
||||||
}
|
}
|
||||||
@@ -171,7 +197,6 @@ func main() {
|
|||||||
GatewayUrl: gatewayUrl,
|
GatewayUrl: gatewayUrl,
|
||||||
UseLogsNewSchema: useLogsNewSchema,
|
UseLogsNewSchema: useLogsNewSchema,
|
||||||
UseTraceNewSchema: useTraceNewSchema,
|
UseTraceNewSchema: useTraceNewSchema,
|
||||||
SkipWebFrontend: skipWebFrontend,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the jwt secret key
|
// Read the jwt secret key
|
||||||
|
|||||||
5
go.mod
5
go.mod
@@ -20,6 +20,7 @@ require (
|
|||||||
github.com/go-kit/log v0.2.1
|
github.com/go-kit/log v0.2.1
|
||||||
github.com/go-redis/redis/v8 v8.11.5
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/go-redis/redismock/v8 v8.11.5
|
github.com/go-redis/redismock/v8 v8.11.5
|
||||||
|
github.com/go-viper/mapstructure/v2 v2.1.0
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/handlers v1.5.1
|
github.com/gorilla/handlers v1.5.1
|
||||||
@@ -29,6 +30,7 @@ require (
|
|||||||
github.com/jmoiron/sqlx v1.3.4
|
github.com/jmoiron/sqlx v1.3.4
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/knadh/koanf v1.5.0
|
github.com/knadh/koanf v1.5.0
|
||||||
|
github.com/knadh/koanf/v2 v2.1.1
|
||||||
github.com/mailru/easyjson v0.7.7
|
github.com/mailru/easyjson v0.7.7
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||||
github.com/oklog/oklog v0.3.2
|
github.com/oklog/oklog v0.3.2
|
||||||
@@ -101,6 +103,7 @@ require (
|
|||||||
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect
|
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
|
github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/go-faster/city v1.0.1 // indirect
|
github.com/go-faster/city v1.0.1 // indirect
|
||||||
github.com/go-faster/errors v0.7.1 // indirect
|
github.com/go-faster/errors v0.7.1 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
||||||
@@ -108,7 +111,6 @@ require (
|
|||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.1.0 // indirect
|
|
||||||
github.com/goccy/go-json v0.10.3 // indirect
|
github.com/goccy/go-json v0.10.3 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||||
@@ -129,7 +131,6 @@ require (
|
|||||||
github.com/jpillora/backoff v1.0.0 // indirect
|
github.com/jpillora/backoff v1.0.0 // indirect
|
||||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||||
github.com/klauspost/compress v1.17.10 // indirect
|
github.com/klauspost/compress v1.17.10 // indirect
|
||||||
github.com/knadh/koanf/v2 v2.1.1 // indirect
|
|
||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/leodido/go-syslog/v4 v4.2.0 // indirect
|
github.com/leodido/go-syslog/v4 v4.2.0 // indirect
|
||||||
github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b // indirect
|
github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b // indirect
|
||||||
|
|||||||
14
pkg/cache/config.go
vendored
14
pkg/cache/config.go
vendored
@@ -4,12 +4,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
go_cache "github.com/patrickmn/go-cache"
|
go_cache "github.com/patrickmn/go-cache"
|
||||||
"go.signoz.io/signoz/pkg/confmap"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config satisfies the confmap.Config interface
|
|
||||||
var _ confmap.Config = (*Config)(nil)
|
|
||||||
|
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
TTL time.Duration `mapstructure:"ttl"`
|
TTL time.Duration `mapstructure:"ttl"`
|
||||||
CleanupInterval time.Duration `mapstructure:"cleanupInterval"`
|
CleanupInterval time.Duration `mapstructure:"cleanupInterval"`
|
||||||
@@ -28,7 +25,11 @@ type Config struct {
|
|||||||
Redis Redis `mapstructure:"redis"`
|
Redis Redis `mapstructure:"redis"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) NewWithDefaults() confmap.Config {
|
func NewConfigFactory() factory.ConfigFactory {
|
||||||
|
return factory.NewConfigFactory(factory.MustNewName("cache"), newConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConfig() factory.Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
Provider: "memory",
|
Provider: "memory",
|
||||||
Memory: Memory{
|
Memory: Memory{
|
||||||
@@ -42,8 +43,9 @@ func (c *Config) NewWithDefaults() confmap.Config {
|
|||||||
DB: 0,
|
DB: 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Validate() error {
|
func (c Config) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
29
pkg/cache/memorycache/provider.go
vendored
29
pkg/cache/memorycache/provider.go
vendored
@@ -7,15 +7,20 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
go_cache "github.com/patrickmn/go-cache"
|
go_cache "github.com/patrickmn/go-cache"
|
||||||
_cache "go.signoz.io/signoz/pkg/cache"
|
"go.signoz.io/signoz/pkg/cache"
|
||||||
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
)
|
)
|
||||||
|
|
||||||
type provider struct {
|
type provider struct {
|
||||||
cc *go_cache.Cache
|
cc *go_cache.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(opts *_cache.Memory) *provider {
|
func NewFactory() factory.ProviderFactory[cache.Cache, cache.Config] {
|
||||||
return &provider{cc: go_cache.New(opts.TTL, opts.CleanupInterval)}
|
return factory.NewProviderFactory(factory.MustNewName("memorycache"), New)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, settings factory.ProviderSettings, config cache.Config) (cache.Cache, error) {
|
||||||
|
return &provider{cc: go_cache.New(config.Memory.TTL, config.Memory.CleanupInterval)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect does nothing
|
// Connect does nothing
|
||||||
@@ -24,11 +29,11 @@ func (c *provider) Connect(_ context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store stores the data in the cache
|
// Store stores the data in the cache
|
||||||
func (c *provider) Store(_ context.Context, cacheKey string, data _cache.CacheableEntity, ttl time.Duration) error {
|
func (c *provider) Store(_ context.Context, cacheKey string, data cache.CacheableEntity, ttl time.Duration) error {
|
||||||
// check if the data being passed is a pointer and is not nil
|
// check if the data being passed is a pointer and is not nil
|
||||||
rv := reflect.ValueOf(data)
|
rv := reflect.ValueOf(data)
|
||||||
if rv.Kind() != reflect.Pointer || rv.IsNil() {
|
if rv.Kind() != reflect.Pointer || rv.IsNil() {
|
||||||
return _cache.WrapCacheableEntityErrors(reflect.TypeOf(data), "inmemory")
|
return cache.WrapCacheableEntityErrors(reflect.TypeOf(data), "inmemory")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cc.Set(cacheKey, data, ttl)
|
c.cc.Set(cacheKey, data, ttl)
|
||||||
@@ -36,32 +41,32 @@ func (c *provider) Store(_ context.Context, cacheKey string, data _cache.Cacheab
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve retrieves the data from the cache
|
// Retrieve retrieves the data from the cache
|
||||||
func (c *provider) Retrieve(_ context.Context, cacheKey string, dest _cache.CacheableEntity, allowExpired bool) (_cache.RetrieveStatus, error) {
|
func (c *provider) Retrieve(_ context.Context, cacheKey string, dest cache.CacheableEntity, allowExpired bool) (cache.RetrieveStatus, error) {
|
||||||
// check if the destination being passed is a pointer and is not nil
|
// check if the destination being passed is a pointer and is not nil
|
||||||
dstv := reflect.ValueOf(dest)
|
dstv := reflect.ValueOf(dest)
|
||||||
if dstv.Kind() != reflect.Pointer || dstv.IsNil() {
|
if dstv.Kind() != reflect.Pointer || dstv.IsNil() {
|
||||||
return _cache.RetrieveStatusError, _cache.WrapCacheableEntityErrors(reflect.TypeOf(dest), "inmemory")
|
return cache.RetrieveStatusError, cache.WrapCacheableEntityErrors(reflect.TypeOf(dest), "inmemory")
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the destination value is settable
|
// check if the destination value is settable
|
||||||
if !dstv.Elem().CanSet() {
|
if !dstv.Elem().CanSet() {
|
||||||
return _cache.RetrieveStatusError, fmt.Errorf("destination value is not settable, %s", dstv.Elem())
|
return cache.RetrieveStatusError, fmt.Errorf("destination value is not settable, %s", dstv.Elem())
|
||||||
}
|
}
|
||||||
|
|
||||||
data, found := c.cc.Get(cacheKey)
|
data, found := c.cc.Get(cacheKey)
|
||||||
if !found {
|
if !found {
|
||||||
return _cache.RetrieveStatusKeyMiss, nil
|
return cache.RetrieveStatusKeyMiss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the type compatbility between the src and dest
|
// check the type compatbility between the src and dest
|
||||||
srcv := reflect.ValueOf(data)
|
srcv := reflect.ValueOf(data)
|
||||||
if !srcv.Type().AssignableTo(dstv.Type()) {
|
if !srcv.Type().AssignableTo(dstv.Type()) {
|
||||||
return _cache.RetrieveStatusError, fmt.Errorf("src type is not assignable to dst type")
|
return cache.RetrieveStatusError, fmt.Errorf("src type is not assignable to dst type")
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the value to from src to dest
|
// set the value to from src to dest
|
||||||
dstv.Elem().Set(srcv.Elem())
|
dstv.Elem().Set(srcv.Elem())
|
||||||
return _cache.RetrieveStatusHit, nil
|
return cache.RetrieveStatusHit, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTTL sets the TTL for the cache entry
|
// SetTTL sets the TTL for the cache entry
|
||||||
@@ -91,6 +96,6 @@ func (c *provider) Close(_ context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Configuration returns the cache configuration
|
// Configuration returns the cache configuration
|
||||||
func (c *provider) Configuration() *_cache.Memory {
|
func (c *provider) Configuration() *cache.Memory {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
62
pkg/cache/memorycache/provider_test.go
vendored
62
pkg/cache/memorycache/provider_test.go
vendored
@@ -7,18 +7,21 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
_cache "go.signoz.io/signoz/pkg/cache"
|
_cache "go.signoz.io/signoz/pkg/cache"
|
||||||
|
"go.signoz.io/signoz/pkg/factory/providertest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestNew tests the New function
|
// TestNew tests the New function
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, c)
|
assert.NotNil(t, c)
|
||||||
assert.NotNil(t, c.cc)
|
assert.NotNil(t, c.(*provider).cc)
|
||||||
assert.NoError(t, c.Connect(context.Background()))
|
assert.NoError(t, c.Connect(context.Background()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,32 +56,35 @@ func (dce DCacheableEntity) UnmarshalBinary(data []byte) error {
|
|||||||
// TestStore tests the Store function
|
// TestStore tests the Store function
|
||||||
// this should fail because of nil pointer error
|
// this should fail because of nil pointer error
|
||||||
func TestStoreWithNilPointer(t *testing.T) {
|
func TestStoreWithNilPointer(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
var storeCacheableEntity *CacheableEntity
|
var storeCacheableEntity *CacheableEntity
|
||||||
assert.Error(t, c.Store(context.Background(), "key", storeCacheableEntity, 10*time.Second))
|
assert.Error(t, c.Store(context.Background(), "key", storeCacheableEntity, 10*time.Second))
|
||||||
}
|
}
|
||||||
|
|
||||||
// this should fail because of no pointer error
|
// this should fail because of no pointer error
|
||||||
func TestStoreWithStruct(t *testing.T) {
|
func TestStoreWithStruct(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
var storeCacheableEntity CacheableEntity
|
var storeCacheableEntity CacheableEntity
|
||||||
assert.Error(t, c.Store(context.Background(), "key", storeCacheableEntity, 10*time.Second))
|
assert.Error(t, c.Store(context.Background(), "key", storeCacheableEntity, 10*time.Second))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStoreWithNonNilPointer(t *testing.T) {
|
func TestStoreWithNonNilPointer(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
@@ -89,11 +95,12 @@ func TestStoreWithNonNilPointer(t *testing.T) {
|
|||||||
|
|
||||||
// TestRetrieve tests the Retrieve function
|
// TestRetrieve tests the Retrieve function
|
||||||
func TestRetrieveWithNilPointer(t *testing.T) {
|
func TestRetrieveWithNilPointer(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
@@ -109,11 +116,12 @@ func TestRetrieveWithNilPointer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRetrieveWitNonPointer(t *testing.T) {
|
func TestRetrieveWitNonPointer(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
@@ -129,11 +137,12 @@ func TestRetrieveWitNonPointer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRetrieveWithDifferentTypes(t *testing.T) {
|
func TestRetrieveWithDifferentTypes(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
@@ -148,11 +157,12 @@ func TestRetrieveWithDifferentTypes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRetrieveWithSameTypes(t *testing.T) {
|
func TestRetrieveWithSameTypes(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
@@ -169,7 +179,8 @@ func TestRetrieveWithSameTypes(t *testing.T) {
|
|||||||
|
|
||||||
// TestSetTTL tests the SetTTL function
|
// TestSetTTL tests the SetTTL function
|
||||||
func TestSetTTL(t *testing.T) {
|
func TestSetTTL(t *testing.T) {
|
||||||
c := New(&_cache.Memory{TTL: 10 * time.Second, CleanupInterval: 1 * time.Second})
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: _cache.Memory{TTL: 10 * time.Second, CleanupInterval: 1 * time.Second}})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
@@ -194,11 +205,12 @@ func TestSetTTL(t *testing.T) {
|
|||||||
|
|
||||||
// TestRemove tests the Remove function
|
// TestRemove tests the Remove function
|
||||||
func TestRemove(t *testing.T) {
|
func TestRemove(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
@@ -216,11 +228,12 @@ func TestRemove(t *testing.T) {
|
|||||||
|
|
||||||
// TestBulkRemove tests the BulkRemove function
|
// TestBulkRemove tests the BulkRemove function
|
||||||
func TestBulkRemove(t *testing.T) {
|
func TestBulkRemove(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
@@ -244,11 +257,12 @@ func TestBulkRemove(t *testing.T) {
|
|||||||
|
|
||||||
// TestCache tests the cache
|
// TestCache tests the cache
|
||||||
func TestCache(t *testing.T) {
|
func TestCache(t *testing.T) {
|
||||||
opts := &_cache.Memory{
|
opts := _cache.Memory{
|
||||||
TTL: 10 * time.Second,
|
TTL: 10 * time.Second,
|
||||||
CleanupInterval: 10 * time.Second,
|
CleanupInterval: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := New(opts)
|
c, err := New(context.Background(), providertest.NewSettings(), _cache.Config{Provider: "memory", Memory: opts})
|
||||||
|
require.NoError(t, err)
|
||||||
storeCacheableEntity := &CacheableEntity{
|
storeCacheableEntity := &CacheableEntity{
|
||||||
Key: "some-random-key",
|
Key: "some-random-key",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
|
|||||||
28
pkg/cache/rediscache/provider.go
vendored
28
pkg/cache/rediscache/provider.go
vendored
@@ -7,17 +7,22 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
_cache "go.signoz.io/signoz/pkg/cache"
|
"go.signoz.io/signoz/pkg/cache"
|
||||||
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type provider struct {
|
type provider struct {
|
||||||
client *redis.Client
|
client *redis.Client
|
||||||
opts *_cache.Redis
|
opts cache.Redis
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(opts *_cache.Redis) *provider {
|
func NewFactory() factory.ProviderFactory[cache.Cache, cache.Config] {
|
||||||
return &provider{opts: opts}
|
return factory.NewProviderFactory(factory.MustNewName("rediscache"), New)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, settings factory.ProviderSettings, config cache.Config) (cache.Cache, error) {
|
||||||
|
return &provider{opts: config.Redis}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithClient creates a new cache with the given client
|
// WithClient creates a new cache with the given client
|
||||||
@@ -36,20 +41,20 @@ func (c *provider) Connect(_ context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store stores the data in the cache
|
// Store stores the data in the cache
|
||||||
func (c *provider) Store(ctx context.Context, cacheKey string, data _cache.CacheableEntity, ttl time.Duration) error {
|
func (c *provider) Store(ctx context.Context, cacheKey string, data cache.CacheableEntity, ttl time.Duration) error {
|
||||||
return c.client.Set(ctx, cacheKey, data, ttl).Err()
|
return c.client.Set(ctx, cacheKey, data, ttl).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve retrieves the data from the cache
|
// Retrieve retrieves the data from the cache
|
||||||
func (c *provider) Retrieve(ctx context.Context, cacheKey string, dest _cache.CacheableEntity, allowExpired bool) (_cache.RetrieveStatus, error) {
|
func (c *provider) Retrieve(ctx context.Context, cacheKey string, dest cache.CacheableEntity, allowExpired bool) (cache.RetrieveStatus, error) {
|
||||||
err := c.client.Get(ctx, cacheKey).Scan(dest)
|
err := c.client.Get(ctx, cacheKey).Scan(dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, redis.Nil) {
|
if errors.Is(err, redis.Nil) {
|
||||||
return _cache.RetrieveStatusKeyMiss, nil
|
return cache.RetrieveStatusKeyMiss, nil
|
||||||
}
|
}
|
||||||
return _cache.RetrieveStatusError, err
|
return cache.RetrieveStatusError, err
|
||||||
}
|
}
|
||||||
return _cache.RetrieveStatusHit, nil
|
return cache.RetrieveStatusHit, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTTL sets the TTL for the cache entry
|
// SetTTL sets the TTL for the cache entry
|
||||||
@@ -87,11 +92,6 @@ func (c *provider) GetClient() *redis.Client {
|
|||||||
return c.client
|
return c.client
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOptions returns the options
|
|
||||||
func (c *provider) GetOptions() *_cache.Redis {
|
|
||||||
return c.opts
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTTL returns the TTL for the cache entry
|
// GetTTL returns the TTL for the cache entry
|
||||||
func (c *provider) GetTTL(ctx context.Context, cacheKey string) time.Duration {
|
func (c *provider) GetTTL(ctx context.Context, cacheKey string) time.Duration {
|
||||||
ttl, err := c.client.TTL(ctx, cacheKey).Result()
|
ttl, err := c.client.TTL(ctx, cacheKey).Result()
|
||||||
|
|||||||
90
pkg/config/conf.go
Normal file
90
pkg/config/conf.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-viper/mapstructure/v2"
|
||||||
|
"github.com/knadh/koanf/providers/confmap"
|
||||||
|
"github.com/knadh/koanf/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KoanfDelimiter string = "::"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Conf is a wrapper around the koanf library.
|
||||||
|
type Conf struct {
|
||||||
|
*koanf.Koanf
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConf creates a new Conf instance.
|
||||||
|
func NewConf() *Conf {
|
||||||
|
return &Conf{koanf.New(KoanfDelimiter)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConfFromMap creates a new Conf instance from a map.
|
||||||
|
func NewConfFromMap(m map[string]any) (*Conf, error) {
|
||||||
|
conf := NewConf()
|
||||||
|
if err := conf.Koanf.Load(confmap.Provider(m, KoanfDelimiter), nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustNewConfFromMap creates a new Conf instance from a map.
|
||||||
|
// It panics if the conf cannot be created.
|
||||||
|
func MustNewConfFromMap(m map[string]any) *Conf {
|
||||||
|
conf, err := NewConfFromMap(m)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge merges the current configuration with the input configuration.
|
||||||
|
func (conf *Conf) Merge(input *Conf) error {
|
||||||
|
return conf.Koanf.Merge(input.Koanf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge merges the current configuration with the input configuration.
|
||||||
|
func (conf *Conf) MergeAt(input *Conf, path string) error {
|
||||||
|
return conf.Koanf.MergeAt(input.Koanf, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal unmarshals the configuration at the given path into the input.
|
||||||
|
// It uses a WeaklyTypedInput to allow for more flexible unmarshalling.
|
||||||
|
func (conf *Conf) Unmarshal(path string, input any) error {
|
||||||
|
dc := &mapstructure.DecoderConfig{
|
||||||
|
TagName: "mapstructure",
|
||||||
|
WeaklyTypedInput: true,
|
||||||
|
DecodeHook: mapstructure.ComposeDecodeHookFunc(
|
||||||
|
mapstructure.StringToSliceHookFunc(","),
|
||||||
|
mapstructure.StringToTimeDurationHookFunc(),
|
||||||
|
mapstructure.TextUnmarshallerHookFunc(),
|
||||||
|
),
|
||||||
|
Result: input,
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf.Koanf.UnmarshalWithConf(path, input, koanf.UnmarshalConf{Tag: "mapstructure", DecoderConfig: dc})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the configuration at the given key.
|
||||||
|
// It decodes the input into a map as per mapstructure.Decode and then merges it into the configuration.
|
||||||
|
func (conf *Conf) Set(key string, input any) error {
|
||||||
|
m := map[string]any{}
|
||||||
|
err := mapstructure.Decode(input, &m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
newConf := NewConf()
|
||||||
|
if err := newConf.Koanf.Load(confmap.Provider(m, KoanfDelimiter), nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := conf.Koanf.MergeAt(newConf.Koanf, key); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
38
pkg/config/conf_test.go
Normal file
38
pkg/config/conf_test.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfMerge(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
conf *Conf
|
||||||
|
input *Conf
|
||||||
|
expected *Conf
|
||||||
|
pass bool
|
||||||
|
}{
|
||||||
|
{name: "Empty", conf: NewConf(), input: NewConf(), expected: NewConf(), pass: true},
|
||||||
|
{name: "Merge", conf: MustNewConfFromMap(map[string]any{"a": "b"}), input: MustNewConfFromMap(map[string]any{"c": "d"}), expected: MustNewConfFromMap(map[string]any{"a": "b", "c": "d"}), pass: true},
|
||||||
|
{name: "NestedMerge", conf: MustNewConfFromMap(map[string]any{"a": map[string]any{"b": "v1", "c": "v2"}}), input: MustNewConfFromMap(map[string]any{"a": map[string]any{"d": "v1", "e": "v2"}}), expected: MustNewConfFromMap(map[string]any{"a": map[string]any{"b": "v1", "c": "v2", "d": "v1", "e": "v2"}}), pass: true},
|
||||||
|
{name: "Override", conf: MustNewConfFromMap(map[string]any{"a": "b"}), input: MustNewConfFromMap(map[string]any{"a": "c"}), expected: MustNewConfFromMap(map[string]any{"a": "c"}), pass: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Parallel()
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
err := tc.conf.Merge(tc.input)
|
||||||
|
if !tc.pass {
|
||||||
|
assert.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expected.Raw(), tc.conf.Raw())
|
||||||
|
assert.Equal(t, tc.expected.Raw(), tc.conf.Raw())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,32 +3,34 @@ package config
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"go.signoz.io/signoz/pkg/cache"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
signozconfmap "go.signoz.io/signoz/pkg/confmap"
|
|
||||||
"go.signoz.io/signoz/pkg/instrumentation"
|
|
||||||
"go.signoz.io/signoz/pkg/web"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// This map contains the default values of all config structs
|
func New(ctx context.Context, resolverConfig ResolverConfig, configFactories []factory.ConfigFactory) (*Conf, error) {
|
||||||
var (
|
// Get the config from the resolver
|
||||||
defaults = map[string]signozconfmap.Config{
|
resolver, err := NewResolver(resolverConfig)
|
||||||
"web": &web.Config{},
|
|
||||||
"cache": &cache.Config{},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config defines the entire configuration of signoz.
|
|
||||||
type Config struct {
|
|
||||||
Instrumentation instrumentation.Config `mapstructure:"instrumentation"`
|
|
||||||
Web web.Config `mapstructure:"web"`
|
|
||||||
Cache cache.Config `mapstructure:"cache"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(ctx context.Context, settings ProviderSettings) (*Config, error) {
|
|
||||||
provider, err := NewProvider(settings)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider.Get(ctx)
|
resolvedConf, err := resolver.Do(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := NewConf()
|
||||||
|
// Set the default configs
|
||||||
|
for _, factory := range configFactories {
|
||||||
|
c := factory.New()
|
||||||
|
if err := conf.Set(factory.Name().String(), c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conf.Merge(resolvedConf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"go.opentelemetry.io/collector/confmap"
|
|
||||||
"go.signoz.io/signoz/pkg/cache"
|
|
||||||
"go.signoz.io/signoz/pkg/confmap/provider/signozenvprovider"
|
|
||||||
"go.signoz.io/signoz/pkg/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNewWithSignozEnvProvider(t *testing.T) {
|
|
||||||
|
|
||||||
t.Setenv("SIGNOZ__WEB__PREFIX", "/web")
|
|
||||||
t.Setenv("SIGNOZ__WEB__DIRECTORY", "/build")
|
|
||||||
t.Setenv("SIGNOZ__CACHE__PROVIDER", "redis")
|
|
||||||
t.Setenv("SIGNOZ__CACHE__REDIS__HOST", "127.0.0.1")
|
|
||||||
|
|
||||||
config, err := New(context.Background(), ProviderSettings{
|
|
||||||
ResolverSettings: confmap.ResolverSettings{
|
|
||||||
URIs: []string{"signozenv:"},
|
|
||||||
ProviderFactories: []confmap.ProviderFactory{
|
|
||||||
signozenvprovider.NewFactory(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
expected := &Config{
|
|
||||||
Web: web.Config{
|
|
||||||
Prefix: "/web",
|
|
||||||
Directory: "/build",
|
|
||||||
},
|
|
||||||
Cache: cache.Config{
|
|
||||||
Provider: "redis",
|
|
||||||
Memory: cache.Memory{
|
|
||||||
TTL: time.Duration(-1),
|
|
||||||
CleanupInterval: 1 * time.Minute,
|
|
||||||
},
|
|
||||||
Redis: cache.Redis{
|
|
||||||
Host: "127.0.0.1",
|
|
||||||
Port: 6379,
|
|
||||||
Password: "",
|
|
||||||
DB: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, expected, config)
|
|
||||||
}
|
|
||||||
71
pkg/config/envprovider/provider.go
Normal file
71
pkg/config/envprovider/provider.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package envprovider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
koanfenv "github.com/knadh/koanf/providers/env"
|
||||||
|
"go.signoz.io/signoz/pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
prefix string = "SIGNOZ_"
|
||||||
|
scheme string = "env"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct{}
|
||||||
|
|
||||||
|
func NewFactory() config.ProviderFactory {
|
||||||
|
return config.NewProviderFactory(New)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(config config.ProviderConfig) config.Provider {
|
||||||
|
return &provider{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Scheme() string {
|
||||||
|
return scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Get(ctx context.Context, uri config.Uri) (*config.Conf, error) {
|
||||||
|
conf := config.NewConf()
|
||||||
|
err := conf.Load(
|
||||||
|
koanfenv.Provider(
|
||||||
|
prefix,
|
||||||
|
// Do not set this to `_`. The correct delimiter is being set by the custom callback provided below.
|
||||||
|
// Since this had to be passed, using `config.KoanfDelimiter` eliminates any possible side effect.
|
||||||
|
config.KoanfDelimiter,
|
||||||
|
func(s string) string {
|
||||||
|
s = strings.ToLower(strings.TrimPrefix(s, prefix))
|
||||||
|
return provider.cb(s, config.KoanfDelimiter)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
return conf, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) cb(s string, delim string) string {
|
||||||
|
delims := []rune(delim)
|
||||||
|
runes := []rune(s)
|
||||||
|
result := make([]rune, 0, len(runes))
|
||||||
|
|
||||||
|
for i := 0; i < len(runes); i++ {
|
||||||
|
// Check for double underscore pattern
|
||||||
|
if i < len(runes)-1 && runes[i] == '_' && runes[i+1] == '_' {
|
||||||
|
result = append(result, '_')
|
||||||
|
i++ // Skip next underscore
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if runes[i] == '_' {
|
||||||
|
result = append(result, delims...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, runes[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
78
pkg/config/envprovider/provider_test.go
Normal file
78
pkg/config/envprovider/provider_test.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package envprovider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.signoz.io/signoz/pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetWithStrings(t *testing.T) {
|
||||||
|
t.Setenv("SIGNOZ_K1_K2", "string")
|
||||||
|
t.Setenv("SIGNOZ_K3__K4", "string")
|
||||||
|
t.Setenv("SIGNOZ_K5__K6_K7__K8", "string")
|
||||||
|
t.Setenv("SIGNOZ_K9___K10", "string")
|
||||||
|
t.Setenv("SIGNOZ_K11____K12", "string")
|
||||||
|
expected := map[string]any{
|
||||||
|
"k1::k2": "string",
|
||||||
|
"k3_k4": "string",
|
||||||
|
"k5_k6::k7_k8": "string",
|
||||||
|
"k9_::k10": "string",
|
||||||
|
"k11__k12": "string",
|
||||||
|
}
|
||||||
|
|
||||||
|
provider := New(config.ProviderConfig{})
|
||||||
|
actual, err := provider.Get(context.Background(), config.MustNewUri("env:"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, expected, actual.All())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetWithGoTypes(t *testing.T) {
|
||||||
|
t.Setenv("SIGNOZ_BOOL", "true")
|
||||||
|
t.Setenv("SIGNOZ_STRING", "string")
|
||||||
|
t.Setenv("SIGNOZ_INT", "1")
|
||||||
|
t.Setenv("SIGNOZ_SLICE", "[1,2]")
|
||||||
|
expected := map[string]any{
|
||||||
|
"bool": "true",
|
||||||
|
"int": "1",
|
||||||
|
"slice": "[1,2]",
|
||||||
|
"string": "string",
|
||||||
|
}
|
||||||
|
|
||||||
|
provider := New(config.ProviderConfig{})
|
||||||
|
actual, err := provider.Get(context.Background(), config.MustNewUri("env:"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, expected, actual.All())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetWithGoTypesWithUnmarshal(t *testing.T) {
|
||||||
|
t.Setenv("SIGNOZ_BOOL", "true")
|
||||||
|
t.Setenv("SIGNOZ_STRING", "string")
|
||||||
|
t.Setenv("SIGNOZ_INT", "1")
|
||||||
|
|
||||||
|
type test struct {
|
||||||
|
Bool bool `mapstructure:"bool"`
|
||||||
|
String string `mapstructure:"string"`
|
||||||
|
Int int `mapstructure:"int"`
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := test{
|
||||||
|
Bool: true,
|
||||||
|
String: "string",
|
||||||
|
Int: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
provider := New(config.ProviderConfig{})
|
||||||
|
conf, err := provider.Get(context.Background(), config.MustNewUri("env:"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
actual := test{}
|
||||||
|
err = conf.Unmarshal("", &actual)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, expected, actual)
|
||||||
|
}
|
||||||
34
pkg/config/fileprovider/provider.go
Normal file
34
pkg/config/fileprovider/provider.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package fileprovider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
koanfyaml "github.com/knadh/koanf/parsers/yaml"
|
||||||
|
koanffile "github.com/knadh/koanf/providers/file"
|
||||||
|
"go.signoz.io/signoz/pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
scheme string = "file"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct{}
|
||||||
|
|
||||||
|
func NewFactory() config.ProviderFactory {
|
||||||
|
return config.NewProviderFactory(New)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(config config.ProviderConfig) config.Provider {
|
||||||
|
return &provider{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Scheme() string {
|
||||||
|
return scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Get(ctx context.Context, uri config.Uri) (*config.Conf, error) {
|
||||||
|
conf := config.NewConf()
|
||||||
|
err := conf.Load(koanffile.Provider(uri.Value()), koanfyaml.Parser())
|
||||||
|
|
||||||
|
return conf, err
|
||||||
|
}
|
||||||
68
pkg/config/fileprovider/provider_test.go
Normal file
68
pkg/config/fileprovider/provider_test.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package fileprovider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.signoz.io/signoz/pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetWithStrings(t *testing.T) {
|
||||||
|
expected := map[string]any{
|
||||||
|
"k1::k2": "string",
|
||||||
|
"k3_k4": "string",
|
||||||
|
"k5_k6::k7_k8": "string",
|
||||||
|
"k9_::k10": "string",
|
||||||
|
"k11__k12": "string",
|
||||||
|
}
|
||||||
|
|
||||||
|
provider := New(config.ProviderConfig{})
|
||||||
|
actual, err := provider.Get(context.Background(), config.MustNewUri("file:"+filepath.Join("testdata", "strings.yaml")))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, expected, actual.All())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetWithGoTypes(t *testing.T) {
|
||||||
|
expected := map[string]any{
|
||||||
|
"bool": true,
|
||||||
|
"int": 1,
|
||||||
|
"slice": []any{1, 2},
|
||||||
|
"string": "string",
|
||||||
|
}
|
||||||
|
|
||||||
|
provider := New(config.ProviderConfig{})
|
||||||
|
actual, err := provider.Get(context.Background(), config.MustNewUri("file:"+filepath.Join("testdata", "gotypes.yaml")))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, expected, actual.All())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetWithGoTypesWithUnmarshal(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
Bool bool `mapstructure:"bool"`
|
||||||
|
String string `mapstructure:"string"`
|
||||||
|
Int int `mapstructure:"int"`
|
||||||
|
Slice []any `mapstructure:"slice"`
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := test{
|
||||||
|
Bool: true,
|
||||||
|
String: "string",
|
||||||
|
Int: 1,
|
||||||
|
Slice: []any{1, 2},
|
||||||
|
}
|
||||||
|
|
||||||
|
provider := New(config.ProviderConfig{})
|
||||||
|
conf, err := provider.Get(context.Background(), config.MustNewUri("file:"+filepath.Join("testdata", "gotypes.yaml")))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
actual := test{}
|
||||||
|
err = conf.Unmarshal("", &actual)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, expected, actual)
|
||||||
|
}
|
||||||
6
pkg/config/fileprovider/testdata/gotypes.yaml
vendored
Normal file
6
pkg/config/fileprovider/testdata/gotypes.yaml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
bool: true
|
||||||
|
string: string
|
||||||
|
int: 1
|
||||||
|
slice:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
8
pkg/config/fileprovider/testdata/strings.yaml
vendored
Normal file
8
pkg/config/fileprovider/testdata/strings.yaml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
k1:
|
||||||
|
k2: string
|
||||||
|
k3_k4: string
|
||||||
|
k5_k6:
|
||||||
|
k7_k8: string
|
||||||
|
k9_:
|
||||||
|
k10: string
|
||||||
|
k11__k12: string
|
||||||
@@ -2,51 +2,38 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"go.opentelemetry.io/collector/confmap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Provides the configuration for signoz.
|
// NewProviderFunc is a function that creates a new provider.
|
||||||
|
type NewProviderFunc = func(ProviderConfig) Provider
|
||||||
|
|
||||||
|
// ProviderFactory is a factory that creates a new provider.
|
||||||
|
type ProviderFactory interface {
|
||||||
|
New(ProviderConfig) Provider
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProviderFactory creates a new provider factory.
|
||||||
|
func NewProviderFactory(f NewProviderFunc) ProviderFactory {
|
||||||
|
return &providerFactory{f: f}
|
||||||
|
}
|
||||||
|
|
||||||
|
// providerFactory is a factory that implements the ProviderFactory interface.
|
||||||
|
type providerFactory struct {
|
||||||
|
f NewProviderFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new provider.
|
||||||
|
func (factory *providerFactory) New(config ProviderConfig) Provider {
|
||||||
|
return factory.f(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderConfig is the configuration for a provider.
|
||||||
|
type ProviderConfig struct{}
|
||||||
|
|
||||||
|
// Provider is an interface that represents a configuration provider.
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
// Get returns the configuration, or error otherwise.
|
// Get returns the configuration for the given URI.
|
||||||
Get(ctx context.Context) (*Config, error)
|
Get(context.Context, Uri) (*Conf, error)
|
||||||
}
|
// Scheme returns the scheme of the provider.
|
||||||
|
Scheme() string
|
||||||
type provider struct {
|
|
||||||
resolver *confmap.Resolver
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProviderSettings are the settings to configure the behavior of the Provider.
|
|
||||||
type ProviderSettings struct {
|
|
||||||
// ResolverSettings are the settings to configure the behavior of the confmap.Resolver.
|
|
||||||
ResolverSettings confmap.ResolverSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewProvider returns a new Provider that provides the entire configuration.
|
|
||||||
// See https://github.com/open-telemetry/opentelemetry-collector/blob/main/otelcol/configprovider.go for
|
|
||||||
// more details
|
|
||||||
func NewProvider(settings ProviderSettings) (Provider, error) {
|
|
||||||
resolver, err := confmap.NewResolver(settings.ResolverSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &provider{
|
|
||||||
resolver: resolver,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *provider) Get(ctx context.Context) (*Config, error) {
|
|
||||||
conf, err := provider.resolver.Resolve(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot resolve configuration: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
config, err := unmarshal(conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot unmarshal configuration: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
87
pkg/config/resolver.go
Normal file
87
pkg/config/resolver.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResolverConfig struct {
|
||||||
|
// Each string or `uri` must follow "<scheme>:<value>" format. This format is compatible with the URI definition
|
||||||
|
// defined at https://datatracker.ietf.org/doc/html/rfc3986".
|
||||||
|
// It is required to have at least one uri.
|
||||||
|
Uris []string
|
||||||
|
|
||||||
|
// ProviderFactories is a slice of Provider factories.
|
||||||
|
// It is required to have at least one factory.
|
||||||
|
ProviderFactories []ProviderFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
type Resolver struct {
|
||||||
|
uris []Uri
|
||||||
|
providers map[string]Provider
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResolver(config ResolverConfig) (*Resolver, error) {
|
||||||
|
if len(config.Uris) == 0 {
|
||||||
|
return nil, errors.New("cannot build resolver, no uris have been provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.ProviderFactories) == 0 {
|
||||||
|
return nil, errors.New("cannot build resolver, no providers have been provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
uris := make([]Uri, len(config.Uris))
|
||||||
|
for i, inputUri := range config.Uris {
|
||||||
|
uri, err := NewUri(inputUri)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
uris[i] = uri
|
||||||
|
}
|
||||||
|
|
||||||
|
providers := make(map[string]Provider, len(config.ProviderFactories))
|
||||||
|
for _, factory := range config.ProviderFactories {
|
||||||
|
provider := factory.New(ProviderConfig{})
|
||||||
|
|
||||||
|
scheme := provider.Scheme()
|
||||||
|
// Check that the scheme is unique.
|
||||||
|
if _, ok := providers[scheme]; ok {
|
||||||
|
return nil, fmt.Errorf("cannot build resolver, duplicate scheme %q found", scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
providers[provider.Scheme()] = provider
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Resolver{
|
||||||
|
uris: uris,
|
||||||
|
providers: providers,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (resolver *Resolver) Do(ctx context.Context) (*Conf, error) {
|
||||||
|
conf := NewConf()
|
||||||
|
|
||||||
|
for _, uri := range resolver.uris {
|
||||||
|
currentConf, err := resolver.get(ctx, uri)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = conf.Merge(currentConf); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot merge config: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (resolver *Resolver) get(ctx context.Context, uri Uri) (*Conf, error) {
|
||||||
|
provider, ok := resolver.providers[uri.scheme]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("cannot find provider with schema %q", uri.scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider.Get(ctx, uri)
|
||||||
|
}
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"go.opentelemetry.io/collector/confmap"
|
|
||||||
)
|
|
||||||
|
|
||||||
// unmarshal converts a confmap.Conf into a Config struct.
|
|
||||||
// It splits the input confmap into a map of key-value pairs, fetches the corresponding
|
|
||||||
// signozconfmap.Config interface by name, merges it with the default config, validates it,
|
|
||||||
// and then creates a new confmap from the parsed map to unmarshal into the Config struct.
|
|
||||||
func unmarshal(conf *confmap.Conf) (*Config, error) {
|
|
||||||
raw := make(map[string]any)
|
|
||||||
if err := conf.Unmarshal(&raw); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed := make(map[string]any)
|
|
||||||
|
|
||||||
// To help the defaults kick in, we need iterate over the default map instead of the raw values
|
|
||||||
for k, v := range defaults {
|
|
||||||
sub, err := conf.Sub(k)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot read config for %q: %w", k, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
d := v.NewWithDefaults()
|
|
||||||
if err := sub.Unmarshal(&d); err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot merge config for %q: %w", k, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = d.Validate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to validate config for for %q: %w", k, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed[k] = d
|
|
||||||
}
|
|
||||||
|
|
||||||
parsedConf := confmap.NewFromStringMap(parsed)
|
|
||||||
config := new(Config)
|
|
||||||
err := parsedConf.Unmarshal(config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot unmarshal config: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
46
pkg/config/uri.go
Normal file
46
pkg/config/uri.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// uriRegex is a regex that matches the URI format. It complies with the URI definition defined at https://datatracker.ietf.org/doc/html/rfc3986.
|
||||||
|
// The format is "<scheme>:<value>".
|
||||||
|
uriRegex = regexp.MustCompile(`(?s:^(?P<Scheme>[A-Za-z][A-Za-z0-9+.-]+):(?P<Value>.*)$)`)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Uri struct {
|
||||||
|
scheme string
|
||||||
|
value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUri(input string) (Uri, error) {
|
||||||
|
submatches := uriRegex.FindStringSubmatch(input)
|
||||||
|
|
||||||
|
if len(submatches) != 3 {
|
||||||
|
return Uri{}, fmt.Errorf("invalid uri: %q", input)
|
||||||
|
}
|
||||||
|
return Uri{
|
||||||
|
scheme: submatches[1],
|
||||||
|
value: submatches[2],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MustNewUri(input string) Uri {
|
||||||
|
uri, err := NewUri(input)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return uri
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uri Uri) Scheme() string {
|
||||||
|
return uri.scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uri Uri) Value() string {
|
||||||
|
return uri.value
|
||||||
|
}
|
||||||
35
pkg/config/uri_test.go
Normal file
35
pkg/config/uri_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewUri(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
input string
|
||||||
|
expected Uri
|
||||||
|
pass bool
|
||||||
|
}{
|
||||||
|
{input: "file:/path/1", expected: Uri{scheme: "file", value: "/path/1"}, pass: true},
|
||||||
|
{input: "file:", expected: Uri{scheme: "file", value: ""}, pass: true},
|
||||||
|
{input: "env:", expected: Uri{scheme: "env", value: ""}, pass: true},
|
||||||
|
{input: "scheme", expected: Uri{}, pass: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
uri, err := NewUri(tc.input)
|
||||||
|
if !tc.pass {
|
||||||
|
assert.Error(t, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotPanics(t, func() { MustNewUri(tc.input) })
|
||||||
|
assert.Equal(t, tc.expected, uri)
|
||||||
|
assert.Equal(t, tc.expected.Scheme(), uri.scheme)
|
||||||
|
assert.Equal(t, tc.expected.Value(), uri.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ func (factory *providerFactory[P, C]) New(ctx context.Context, settings Provider
|
|||||||
return factory.newProviderFunc(ctx, settings, config)
|
return factory.newProviderFunc(ctx, settings, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewProviderFactory creates a new provider factory.
|
||||||
func NewProviderFactory[P Provider, C Config](name Name, newProviderFunc NewProviderFunc[P, C]) ProviderFactory[P, C] {
|
func NewProviderFactory[P Provider, C Config](name Name, newProviderFunc NewProviderFunc[P, C]) ProviderFactory[P, C] {
|
||||||
return &providerFactory[P, C]{
|
return &providerFactory[P, C]{
|
||||||
name: name,
|
name: name,
|
||||||
@@ -32,7 +33,8 @@ func NewProviderFactory[P Provider, C Config](name Name, newProviderFunc NewProv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFromFactory[P Provider, C Config](ctx context.Context, settings ProviderSettings, config C, factories NamedMap[ProviderFactory[P, C]], key string) (p P, err error) {
|
// NewProviderFromNamedMap creates a new provider from a factory based on the input key.
|
||||||
|
func NewProviderFromNamedMap[P Provider, C Config](ctx context.Context, settings ProviderSettings, config C, factories NamedMap[ProviderFactory[P, C]], key string) (p P, err error) {
|
||||||
providerFactory, err := factories.Get(key)
|
providerFactory, err := factories.Get(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ func TestNewProviderFactoryFromFactory(t *testing.T) {
|
|||||||
|
|
||||||
m := MustNewNamedMap(pf)
|
m := MustNewNamedMap(pf)
|
||||||
assert.Equal(t, MustNewName("p1"), pf.Name())
|
assert.Equal(t, MustNewName("p1"), pf.Name())
|
||||||
p, err := NewFromFactory(context.Background(), ProviderSettings{}, pc1{}, m, "p1")
|
p, err := NewProviderFromNamedMap(context.Background(), ProviderSettings{}, pc1{}, m, "p1")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.IsType(t, p1{}, p)
|
assert.IsType(t, p1{}, p)
|
||||||
|
|
||||||
_, err = NewFromFactory(context.Background(), ProviderSettings{}, pc1{}, m, "p2")
|
_, err = NewProviderFromNamedMap(context.Background(), ProviderSettings{}, pc1{}, m, "p2")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
10
pkg/factory/providertest/setting.go
Normal file
10
pkg/factory/providertest/setting.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package providertest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
|
"go.signoz.io/signoz/pkg/instrumentation/instrumentationtest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewSettings() factory.ProviderSettings {
|
||||||
|
return instrumentationtest.New().ToProviderSettings()
|
||||||
|
}
|
||||||
59
pkg/signoz/config.go
Normal file
59
pkg/signoz/config.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package signoz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.signoz.io/signoz/pkg/cache"
|
||||||
|
"go.signoz.io/signoz/pkg/config"
|
||||||
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
|
"go.signoz.io/signoz/pkg/instrumentation"
|
||||||
|
"go.signoz.io/signoz/pkg/sqlmigration"
|
||||||
|
"go.signoz.io/signoz/pkg/sqlmigrator"
|
||||||
|
"go.signoz.io/signoz/pkg/sqlstore"
|
||||||
|
"go.signoz.io/signoz/pkg/web"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProviderConfig struct {
|
||||||
|
// Map of all cache provider factories
|
||||||
|
CacheProviderFactories factory.NamedMap[factory.ProviderFactory[cache.Cache, cache.Config]]
|
||||||
|
|
||||||
|
// Map of all web provider factories
|
||||||
|
WebProviderFactories factory.NamedMap[factory.ProviderFactory[web.Web, web.Config]]
|
||||||
|
|
||||||
|
// Map of all sqlstore provider factories
|
||||||
|
SQLStoreProviderFactories factory.NamedMap[factory.ProviderFactory[sqlstore.SQLStore, sqlstore.Config]]
|
||||||
|
|
||||||
|
// Map of all sql migration provider factories
|
||||||
|
SQLMigrationProviderFactories factory.NamedMap[factory.ProviderFactory[sqlmigration.SQLMigration, sqlmigration.Config]]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config defines the entire input configuration of signoz.
|
||||||
|
type Config struct {
|
||||||
|
Instrumentation instrumentation.Config `mapstructure:"instrumentation"`
|
||||||
|
Web web.Config `mapstructure:"web"`
|
||||||
|
Cache cache.Config `mapstructure:"cache"`
|
||||||
|
SQLStore sqlstore.Config `mapstructure:"sqlstore"`
|
||||||
|
SQLMigrator sqlmigrator.Config `mapstructure:"sqlmigrator"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig(ctx context.Context, resolverConfig config.ResolverConfig) (Config, error) {
|
||||||
|
configFactories := []factory.ConfigFactory{
|
||||||
|
instrumentation.NewConfigFactory(),
|
||||||
|
web.NewConfigFactory(),
|
||||||
|
cache.NewConfigFactory(),
|
||||||
|
sqlstore.NewConfigFactory(),
|
||||||
|
sqlmigrator.NewConfigFactory(),
|
||||||
|
}
|
||||||
|
|
||||||
|
conf, err := config.New(ctx, resolverConfig, configFactories)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
if err := conf.Unmarshal("", &config); err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
package signoz
|
package signoz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"go.signoz.io/signoz/pkg/cache"
|
"go.signoz.io/signoz/pkg/cache"
|
||||||
"go.signoz.io/signoz/pkg/cache/memorycache"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/cache/rediscache"
|
"go.signoz.io/signoz/pkg/instrumentation"
|
||||||
"go.signoz.io/signoz/pkg/config"
|
"go.signoz.io/signoz/pkg/version"
|
||||||
|
|
||||||
"go.signoz.io/signoz/pkg/web"
|
"go.signoz.io/signoz/pkg/web"
|
||||||
"go.signoz.io/signoz/pkg/web/routerweb"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SigNoz struct {
|
type SigNoz struct {
|
||||||
@@ -15,19 +16,41 @@ type SigNoz struct {
|
|||||||
Web web.Web
|
Web web.Web
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config *config.Config, skipWebFrontend bool) (*SigNoz, error) {
|
func New(
|
||||||
var cache cache.Cache
|
ctx context.Context,
|
||||||
|
config Config,
|
||||||
// init for the cache
|
providerConfig ProviderConfig,
|
||||||
switch config.Cache.Provider {
|
) (*SigNoz, error) {
|
||||||
case "memory":
|
// Initialize instrumentation
|
||||||
cache = memorycache.New(&config.Cache.Memory)
|
instrumentation, err := instrumentation.New(ctx, version.Build{}, config.Instrumentation)
|
||||||
case "redis":
|
if err != nil {
|
||||||
cache = rediscache.New(&config.Cache.Redis)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
web, err := routerweb.New(zap.L(), config.Web)
|
// Get the provider settings from instrumentation
|
||||||
if err != nil && !skipWebFrontend {
|
providerSettings := instrumentation.ToProviderSettings()
|
||||||
|
|
||||||
|
// Initialize cache from the available cache provider factories
|
||||||
|
cache, err := factory.NewProviderFromNamedMap(
|
||||||
|
ctx,
|
||||||
|
providerSettings,
|
||||||
|
config.Cache,
|
||||||
|
providerConfig.CacheProviderFactories,
|
||||||
|
config.Cache.Provider,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize web from the available web provider factories
|
||||||
|
web, err := factory.NewProviderFromNamedMap(
|
||||||
|
ctx,
|
||||||
|
providerSettings,
|
||||||
|
config.Web,
|
||||||
|
providerConfig.WebProviderFactories,
|
||||||
|
config.Web.Provider(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package migration
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/sqlmigrator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type addDataMigrations struct{}
|
type addDataMigrations struct{}
|
||||||
|
|
||||||
func NewAddDataMigrationsFactory() factory.ProviderFactory[sqlmigrator.SQLMigration, sqlmigrator.Config] {
|
func NewAddDataMigrationsFactory() factory.ProviderFactory[SQLMigration, Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("add_data_migrations"), newAddDataMigrations)
|
return factory.NewProviderFactory(factory.MustNewName("add_data_migrations"), newAddDataMigrations)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddDataMigrations(_ context.Context, _ factory.ProviderSettings, _ sqlmigrator.Config) (sqlmigrator.SQLMigration, error) {
|
func newAddDataMigrations(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||||
return &addDataMigrations{}, nil
|
return &addDataMigrations{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package migration
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/sqlmigrator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type addOrganization struct{}
|
type addOrganization struct{}
|
||||||
|
|
||||||
func NewAddOrganizationFactory() factory.ProviderFactory[sqlmigrator.SQLMigration, sqlmigrator.Config] {
|
func NewAddOrganizationFactory() factory.ProviderFactory[SQLMigration, Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("add_organization"), newAddOrganization)
|
return factory.NewProviderFactory(factory.MustNewName("add_organization"), newAddOrganization)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddOrganization(_ context.Context, _ factory.ProviderSettings, _ sqlmigrator.Config) (sqlmigrator.SQLMigration, error) {
|
func newAddOrganization(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||||
return &addOrganization{}, nil
|
return &addOrganization{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package migration
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/sqlmigrator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type addPreferences struct{}
|
type addPreferences struct{}
|
||||||
|
|
||||||
func NewAddPreferencesFactory() factory.ProviderFactory[sqlmigrator.SQLMigration, sqlmigrator.Config] {
|
func NewAddPreferencesFactory() factory.ProviderFactory[SQLMigration, Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("add_preferences"), newAddPreferences)
|
return factory.NewProviderFactory(factory.MustNewName("add_preferences"), newAddPreferences)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddPreferences(_ context.Context, _ factory.ProviderSettings, _ sqlmigrator.Config) (sqlmigrator.SQLMigration, error) {
|
func newAddPreferences(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||||
return &addPreferences{}, nil
|
return &addPreferences{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package migration
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/sqlmigrator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type addDashboards struct{}
|
type addDashboards struct{}
|
||||||
|
|
||||||
func NewAddDashboardsFactory() factory.ProviderFactory[sqlmigrator.SQLMigration, sqlmigrator.Config] {
|
func NewAddDashboardsFactory() factory.ProviderFactory[SQLMigration, Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("add_dashboards"), newAddDashboards)
|
return factory.NewProviderFactory(factory.MustNewName("add_dashboards"), newAddDashboards)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddDashboards(_ context.Context, _ factory.ProviderSettings, _ sqlmigrator.Config) (sqlmigrator.SQLMigration, error) {
|
func newAddDashboards(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||||
return &addDashboards{}, nil
|
return &addDashboards{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +95,8 @@ func (migration *addDashboards) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
NewAddColumn().
|
NewAddColumn().
|
||||||
Table("rules").
|
Table("rules").
|
||||||
ColumnExpr("created_at datetime").
|
ColumnExpr("created_at datetime").
|
||||||
Apply(sqlmigrator.WrapIfNotExists(ctx, db, "rules", "created_at")).
|
Apply(WrapIfNotExists(ctx, db, "rules", "created_at")).
|
||||||
Exec(ctx); err != nil && err != sqlmigrator.ErrNoExecute {
|
Exec(ctx); err != nil && err != ErrNoExecute {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,8 +105,8 @@ func (migration *addDashboards) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
NewAddColumn().
|
NewAddColumn().
|
||||||
Table("rules").
|
Table("rules").
|
||||||
ColumnExpr("created_by TEXT").
|
ColumnExpr("created_by TEXT").
|
||||||
Apply(sqlmigrator.WrapIfNotExists(ctx, db, "rules", "created_by")).
|
Apply(WrapIfNotExists(ctx, db, "rules", "created_by")).
|
||||||
Exec(ctx); err != nil && err != sqlmigrator.ErrNoExecute {
|
Exec(ctx); err != nil && err != ErrNoExecute {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,8 +115,8 @@ func (migration *addDashboards) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
NewAddColumn().
|
NewAddColumn().
|
||||||
Table("rules").
|
Table("rules").
|
||||||
ColumnExpr("updated_by TEXT").
|
ColumnExpr("updated_by TEXT").
|
||||||
Apply(sqlmigrator.WrapIfNotExists(ctx, db, "rules", "updated_by")).
|
Apply(WrapIfNotExists(ctx, db, "rules", "updated_by")).
|
||||||
Exec(ctx); err != nil && err != sqlmigrator.ErrNoExecute {
|
Exec(ctx); err != nil && err != ErrNoExecute {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,8 +125,8 @@ func (migration *addDashboards) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
NewAddColumn().
|
NewAddColumn().
|
||||||
Table("dashboards").
|
Table("dashboards").
|
||||||
ColumnExpr("created_by TEXT").
|
ColumnExpr("created_by TEXT").
|
||||||
Apply(sqlmigrator.WrapIfNotExists(ctx, db, "dashboards", "created_by")).
|
Apply(WrapIfNotExists(ctx, db, "dashboards", "created_by")).
|
||||||
Exec(ctx); err != nil && err != sqlmigrator.ErrNoExecute {
|
Exec(ctx); err != nil && err != ErrNoExecute {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,8 +135,8 @@ func (migration *addDashboards) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
NewAddColumn().
|
NewAddColumn().
|
||||||
Table("dashboards").
|
Table("dashboards").
|
||||||
ColumnExpr("updated_by TEXT").
|
ColumnExpr("updated_by TEXT").
|
||||||
Apply(sqlmigrator.WrapIfNotExists(ctx, db, "dashboards", "updated_by")).
|
Apply(WrapIfNotExists(ctx, db, "dashboards", "updated_by")).
|
||||||
Exec(ctx); err != nil && err != sqlmigrator.ErrNoExecute {
|
Exec(ctx); err != nil && err != ErrNoExecute {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +145,8 @@ func (migration *addDashboards) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
NewAddColumn().
|
NewAddColumn().
|
||||||
Table("dashboards").
|
Table("dashboards").
|
||||||
ColumnExpr("locked INTEGER DEFAULT 0").
|
ColumnExpr("locked INTEGER DEFAULT 0").
|
||||||
Apply(sqlmigrator.WrapIfNotExists(ctx, db, "dashboards", "locked")).
|
Apply(WrapIfNotExists(ctx, db, "dashboards", "locked")).
|
||||||
Exec(ctx); err != nil && err != sqlmigrator.ErrNoExecute {
|
Exec(ctx); err != nil && err != ErrNoExecute {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package migration
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/sqlmigrator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type addSavedViews struct{}
|
type addSavedViews struct{}
|
||||||
|
|
||||||
func NewAddSavedViewsFactory() factory.ProviderFactory[sqlmigrator.SQLMigration, sqlmigrator.Config] {
|
func NewAddSavedViewsFactory() factory.ProviderFactory[SQLMigration, Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("add_saved_views"), newAddSavedViews)
|
return factory.NewProviderFactory(factory.MustNewName("add_saved_views"), newAddSavedViews)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddSavedViews(_ context.Context, _ factory.ProviderSettings, _ sqlmigrator.Config) (sqlmigrator.SQLMigration, error) {
|
func newAddSavedViews(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||||
return &addSavedViews{}, nil
|
return &addSavedViews{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package migration
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/sqlmigrator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type addAgents struct{}
|
type addAgents struct{}
|
||||||
|
|
||||||
func NewAddAgentsFactory() factory.ProviderFactory[sqlmigrator.SQLMigration, sqlmigrator.Config] {
|
func NewAddAgentsFactory() factory.ProviderFactory[SQLMigration, Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("add_agents"), newAddAgents)
|
return factory.NewProviderFactory(factory.MustNewName("add_agents"), newAddAgents)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddAgents(_ context.Context, _ factory.ProviderSettings, _ sqlmigrator.Config) (sqlmigrator.SQLMigration, error) {
|
func newAddAgents(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||||
return &addAgents{}, nil
|
return &addAgents{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package migration
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/sqlmigrator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type addPipelines struct{}
|
type addPipelines struct{}
|
||||||
|
|
||||||
func NewAddPipelinesFactory() factory.ProviderFactory[sqlmigrator.SQLMigration, sqlmigrator.Config] {
|
func NewAddPipelinesFactory() factory.ProviderFactory[SQLMigration, Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("add_pipelines"), newAddPipelines)
|
return factory.NewProviderFactory(factory.MustNewName("add_pipelines"), newAddPipelines)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddPipelines(_ context.Context, _ factory.ProviderSettings, _ sqlmigrator.Config) (sqlmigrator.SQLMigration, error) {
|
func newAddPipelines(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||||
return &addPipelines{}, nil
|
return &addPipelines{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package migration
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/sqlmigrator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type addIntegrations struct{}
|
type addIntegrations struct{}
|
||||||
|
|
||||||
func NewAddIntegrationsFactory() factory.ProviderFactory[sqlmigrator.SQLMigration, sqlmigrator.Config] {
|
func NewAddIntegrationsFactory() factory.ProviderFactory[SQLMigration, Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("add_integrations"), newAddIntegrations)
|
return factory.NewProviderFactory(factory.MustNewName("add_integrations"), newAddIntegrations)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAddIntegrations(_ context.Context, _ factory.ProviderSettings, _ sqlmigrator.Config) (sqlmigrator.SQLMigration, error) {
|
func newAddIntegrations(_ context.Context, _ factory.ProviderSettings, _ Config) (SQLMigration, error) {
|
||||||
return &addIntegrations{}, nil
|
return &addIntegrations{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
19
pkg/sqlmigration/config.go
Normal file
19
pkg/sqlmigration/config.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package sqlmigration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct{}
|
||||||
|
|
||||||
|
func NewConfigFactory() factory.ConfigFactory {
|
||||||
|
return factory.NewConfigFactory(factory.MustNewName("sqlmigration"), newConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConfig() factory.Config {
|
||||||
|
return Config{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Config) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package sqlmigrator
|
package sqlmigration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -11,11 +11,22 @@ import (
|
|||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SQLMigration is the interface for a single migration.
|
||||||
|
type SQLMigration interface {
|
||||||
|
// Register registers the migration with the given migrations. Each migration needs to be registered
|
||||||
|
//in a dedicated `*.go` file so that the correct migration semantics can be detected.
|
||||||
|
Register(*migrate.Migrations) error
|
||||||
|
// Up runs the migration.
|
||||||
|
Up(context.Context, *bun.DB) error
|
||||||
|
// Down rolls back the migration.
|
||||||
|
Down(context.Context, *bun.DB) error
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNoExecute = errors.New("no execute")
|
ErrNoExecute = errors.New("no execute")
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewMigrations(
|
func New(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
settings factory.ProviderSettings,
|
settings factory.ProviderSettings,
|
||||||
config Config,
|
config Config,
|
||||||
@@ -38,13 +49,13 @@ func NewMigrations(
|
|||||||
return migrations, nil
|
return migrations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustNewMigrations(
|
func MustNew(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
settings factory.ProviderSettings,
|
settings factory.ProviderSettings,
|
||||||
config Config,
|
config Config,
|
||||||
factories factory.NamedMap[factory.ProviderFactory[SQLMigration, Config]],
|
factories factory.NamedMap[factory.ProviderFactory[SQLMigration, Config]],
|
||||||
) *migrate.Migrations {
|
) *migrate.Migrations {
|
||||||
migrations, err := NewMigrations(ctx, settings, config, factories)
|
migrations, err := New(ctx, settings, config, factories)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package sqlmigrator
|
package sqlmigrationtest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,12 +6,13 @@ import (
|
|||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
|
"go.signoz.io/signoz/pkg/sqlmigration"
|
||||||
)
|
)
|
||||||
|
|
||||||
type noopMigration struct{}
|
type noopMigration struct{}
|
||||||
|
|
||||||
func NoopMigrationFactory() factory.ProviderFactory[SQLMigration, Config] {
|
func NoopMigrationFactory() factory.ProviderFactory[sqlmigration.SQLMigration, sqlmigration.Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("noop"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) {
|
return factory.NewProviderFactory(factory.MustNewName("noop"), func(_ context.Context, _ factory.ProviderSettings, _ sqlmigration.Config) (sqlmigration.SQLMigration, error) {
|
||||||
return &noopMigration{}, nil
|
return &noopMigration{}, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.signoz.io/signoz/pkg/factory"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/instrumentation/instrumentationtest"
|
"go.signoz.io/signoz/pkg/instrumentation/instrumentationtest"
|
||||||
|
"go.signoz.io/signoz/pkg/sqlmigration"
|
||||||
|
"go.signoz.io/signoz/pkg/sqlmigration/sqlmigrationtest"
|
||||||
"go.signoz.io/signoz/pkg/sqlstore"
|
"go.signoz.io/signoz/pkg/sqlstore"
|
||||||
"go.signoz.io/signoz/pkg/sqlstore/sqlstoretest"
|
"go.signoz.io/signoz/pkg/sqlstore/sqlstoretest"
|
||||||
)
|
)
|
||||||
@@ -33,7 +35,7 @@ func TestMigratorWithSqliteAndNoopMigration(t *testing.T) {
|
|||||||
ctx,
|
ctx,
|
||||||
providerSettings,
|
providerSettings,
|
||||||
sqlstore,
|
sqlstore,
|
||||||
MustNewMigrations(ctx, providerSettings, migrationConfig, factory.MustNewNamedMap(NoopMigrationFactory())),
|
sqlmigration.MustNew(ctx, providerSettings, sqlmigration.Config{}, factory.MustNewNamedMap(sqlmigrationtest.NoopMigrationFactory())),
|
||||||
migrationConfig,
|
migrationConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ package sqlmigrator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/uptrace/bun"
|
|
||||||
"github.com/uptrace/bun/migrate"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SQLMigrator is the interface for the SQLMigrator.
|
// SQLMigrator is the interface for the SQLMigrator.
|
||||||
@@ -14,14 +11,3 @@ type SQLMigrator interface {
|
|||||||
// Rollback rolls back the database. Rollback acquires a lock on the database and rolls back the migrations.
|
// Rollback rolls back the database. Rollback acquires a lock on the database and rolls back the migrations.
|
||||||
Rollback(context.Context) error
|
Rollback(context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLMigration is the interface for a single migration.
|
|
||||||
type SQLMigration interface {
|
|
||||||
// Register registers the migration with the given migrations. Each migration needs to be registered
|
|
||||||
//in a dedicated `*.go` file so that the correct migration semantics can be detected.
|
|
||||||
Register(*migrate.Migrations) error
|
|
||||||
// Up runs the migration.
|
|
||||||
Up(context.Context, *bun.DB) error
|
|
||||||
// Down rolls back the migration.
|
|
||||||
Down(context.Context, *bun.DB) error
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package web
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.signoz.io/signoz/pkg/confmap"
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config satisfies the confmap.Config interface
|
|
||||||
var _ confmap.Config = (*Config)(nil)
|
|
||||||
|
|
||||||
// Config holds the configuration for web.
|
// Config holds the configuration for web.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
// Whether the web package is enabled.
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
// The prefix to serve the files from
|
// The prefix to serve the files from
|
||||||
Prefix string `mapstructure:"prefix"`
|
Prefix string `mapstructure:"prefix"`
|
||||||
// The directory containing the static build files. The root of this directory should
|
// The directory containing the static build files. The root of this directory should
|
||||||
@@ -16,14 +15,26 @@ type Config struct {
|
|||||||
Directory string `mapstructure:"directory"`
|
Directory string `mapstructure:"directory"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) NewWithDefaults() confmap.Config {
|
func NewConfigFactory() factory.ConfigFactory {
|
||||||
|
return factory.NewConfigFactory(factory.MustNewName("web"), newConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConfig() factory.Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
|
Enabled: true,
|
||||||
Prefix: "/",
|
Prefix: "/",
|
||||||
Directory: "/etc/signoz/web",
|
Directory: "/etc/signoz/web",
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Validate() error {
|
func (c Config) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Config) Provider() string {
|
||||||
|
if c.Enabled {
|
||||||
|
return "router"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "noop"
|
||||||
|
}
|
||||||
|
|||||||
45
pkg/web/config_test.go
Normal file
45
pkg/web/config_test.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.signoz.io/signoz/pkg/config"
|
||||||
|
"go.signoz.io/signoz/pkg/config/envprovider"
|
||||||
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewWithEnvProvider(t *testing.T) {
|
||||||
|
t.Setenv("SIGNOZ_WEB_PREFIX", "/web")
|
||||||
|
t.Setenv("SIGNOZ_WEB_ENABLED", "false")
|
||||||
|
|
||||||
|
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("web", actual)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
def := NewConfigFactory().New().(*Config)
|
||||||
|
|
||||||
|
expected := &Config{
|
||||||
|
Enabled: false,
|
||||||
|
Prefix: "/web",
|
||||||
|
Directory: def.Directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, expected, actual)
|
||||||
|
}
|
||||||
@@ -11,6 +11,10 @@ import (
|
|||||||
|
|
||||||
type provider struct{}
|
type provider struct{}
|
||||||
|
|
||||||
|
func NewFactory() factory.ProviderFactory[web.Web, web.Config] {
|
||||||
|
return factory.NewProviderFactory(factory.MustNewName("noopweb"), New)
|
||||||
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, settings factory.ProviderSettings, config web.Config) (web.Web, error) {
|
func New(ctx context.Context, settings factory.ProviderSettings, config web.Config) (web.Web, error) {
|
||||||
return &provider{}, nil
|
return &provider{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package routerweb
|
package routerweb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -8,26 +9,25 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"go.signoz.io/signoz/pkg/factory"
|
||||||
"go.signoz.io/signoz/pkg/http/middleware"
|
"go.signoz.io/signoz/pkg/http/middleware"
|
||||||
"go.signoz.io/signoz/pkg/web"
|
"go.signoz.io/signoz/pkg/web"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
indexFileName string = "index.html"
|
indexFileName string = "index.html"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Web struct {
|
type provider struct {
|
||||||
logger *zap.Logger
|
config web.Config
|
||||||
cfg web.Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(logger *zap.Logger, cfg web.Config) (*Web, error) {
|
func NewFactory() factory.ProviderFactory[web.Web, web.Config] {
|
||||||
if logger == nil {
|
return factory.NewProviderFactory(factory.MustNewName("routerweb"), New)
|
||||||
return nil, fmt.Errorf("cannot build web, logger is required")
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fi, err := os.Stat(cfg.Directory)
|
func New(ctx context.Context, settings factory.ProviderSettings, config web.Config) (web.Web, error) {
|
||||||
|
fi, err := os.Stat(config.Directory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot access web directory: %w", err)
|
return nil, fmt.Errorf("cannot access web directory: %w", err)
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ func New(logger *zap.Logger, cfg web.Config) (*Web, error) {
|
|||||||
return nil, fmt.Errorf("web directory is not a directory")
|
return nil, fmt.Errorf("web directory is not a directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
fi, err = os.Stat(filepath.Join(cfg.Directory, indexFileName))
|
fi, err = os.Stat(filepath.Join(config.Directory, indexFileName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot access %q in web directory: %w", indexFileName, err)
|
return nil, fmt.Errorf("cannot access %q in web directory: %w", indexFileName, err)
|
||||||
}
|
}
|
||||||
@@ -46,19 +46,18 @@ func New(logger *zap.Logger, cfg web.Config) (*Web, error) {
|
|||||||
return nil, fmt.Errorf("%q does not exist", indexFileName)
|
return nil, fmt.Errorf("%q does not exist", indexFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Web{
|
return &provider{
|
||||||
logger: logger.Named("go.signoz.io/pkg/web"),
|
config: config,
|
||||||
cfg: cfg,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web *Web) AddToRouter(router *mux.Router) error {
|
func (provider *provider) AddToRouter(router *mux.Router) error {
|
||||||
cache := middleware.NewCache(7 * 24 * time.Hour)
|
cache := middleware.NewCache(7 * 24 * time.Hour)
|
||||||
err := router.PathPrefix(web.cfg.Prefix).
|
err := router.PathPrefix(provider.config.Prefix).
|
||||||
Handler(
|
Handler(
|
||||||
http.StripPrefix(
|
http.StripPrefix(
|
||||||
web.cfg.Prefix,
|
provider.config.Prefix,
|
||||||
cache.Wrap(http.HandlerFunc(web.ServeHTTP)),
|
cache.Wrap(http.HandlerFunc(provider.ServeHTTP)),
|
||||||
),
|
),
|
||||||
).GetError()
|
).GetError()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -68,15 +67,15 @@ func (web *Web) AddToRouter(router *mux.Router) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web *Web) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (provider *provider) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
// Join internally call path.Clean to prevent directory traversal
|
// Join internally call path.Clean to prevent directory traversal
|
||||||
path := filepath.Join(web.cfg.Directory, req.URL.Path)
|
path := filepath.Join(provider.config.Directory, req.URL.Path)
|
||||||
|
|
||||||
// check whether a file exists or is a directory at the given path
|
// check whether a file exists or is a directory at the given path
|
||||||
fi, err := os.Stat(path)
|
fi, err := os.Stat(path)
|
||||||
if os.IsNotExist(err) || fi.IsDir() {
|
if os.IsNotExist(err) || fi.IsDir() {
|
||||||
// file does not exist or path is a directory, serve index.html
|
// file does not exist or path is a directory, serve index.html
|
||||||
http.ServeFile(rw, req, filepath.Join(web.cfg.Directory, indexFileName))
|
http.ServeFile(rw, req, filepath.Join(provider.config.Directory, indexFileName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,5 +88,5 @@ func (web *Web) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, use http.FileServer to serve the static file
|
// otherwise, use http.FileServer to serve the static file
|
||||||
http.FileServer(http.Dir(web.cfg.Directory)).ServeHTTP(rw, req)
|
http.FileServer(http.Dir(provider.config.Directory)).ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package routerweb
|
package routerweb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -11,8 +12,8 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.signoz.io/signoz/pkg/factory/providertest"
|
||||||
"go.signoz.io/signoz/pkg/web"
|
"go.signoz.io/signoz/pkg/web"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServeHttpWithoutPrefix(t *testing.T) {
|
func TestServeHttpWithoutPrefix(t *testing.T) {
|
||||||
@@ -23,7 +24,7 @@ func TestServeHttpWithoutPrefix(t *testing.T) {
|
|||||||
expected, err := io.ReadAll(fi)
|
expected, err := io.ReadAll(fi)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
web, err := New(zap.NewNop(), web.Config{Prefix: "/", Directory: filepath.Join("testdata")})
|
web, err := New(context.Background(), providertest.NewSettings(), web.Config{Prefix: "/", Directory: filepath.Join("testdata")})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
@@ -88,7 +89,7 @@ func TestServeHttpWithPrefix(t *testing.T) {
|
|||||||
expected, err := io.ReadAll(fi)
|
expected, err := io.ReadAll(fi)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
web, err := New(zap.NewNop(), web.Config{Prefix: "/web", Directory: filepath.Join("testdata")})
|
web, err := New(context.Background(), providertest.NewSettings(), web.Config{Prefix: "/web", Directory: filepath.Join("testdata")})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
|
|||||||
Reference in New Issue
Block a user