Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Installation is done through the use of a helm chart.
<!-- x-release-please-start-version -->
```
helm install myrelease oci://ghcr.io/robbert229/jaeger-postgresql/charts/jaeger-postgresql \
--version v1.6.0 \
--version v1.7.0 \
--set database.url='postgresql://postgres:password@database:5432/jaeger'
```
<!-- x-release-please-end -->
Expand Down
33 changes: 22 additions & 11 deletions charts/jaeger-postgresql/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,28 @@ spec:
{{- toYaml .Values.service.podSecurityContext | nindent 8 }}
containers:
- name: jaeger-postgresql
args:
- "--log-level"
- "{{ .Values.service.logLevel}}"
- "--database.url"
- "{{ .Values.database.url }}"
- "--database.max-conns"
- "{{ .Values.database.maxConns}}"
- "--grpc-server.host-port"
- "0.0.0.0:12345"
- "--admin.http.host-port"
- "0.0.0.0:12346"
env:
{{- range $key, $value := .Values.extraEnvs }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
- name: JAEGER_POSTGRESQL_LOG_LEVEL
value: {{ .Values.service.logLevel | quote }}
- name: JAEGER_POSTGRESQL_DATABASE_MAX_CONNS
value: {{ .Values.database.maxConns | quote }}
- name: JAEGER_POSTGRESQL_DATABASE_URL
{{ with .Values.database.urlFromSecret }}
valueFrom:
secretKeyRef:
name: {{ .name }}
key: {{ .key }}
{{ else }}
value: {{ .Values.database.url | quote }}
{{ end }}
- name: JAEGER_POSTGRESQL_GRPC_SERVER_HOST_PORT
value: "0.0.0.0:12345"
- name: JAEGER_POSTGRESQL_ADMIN_HTTP_HOST_PORT
value: "0.0.0.0:12346"
securityContext:
{{- toYaml .Values.service.securityContext | nindent 12 }}
image: "{{ .Values.service.image }}"
Expand Down
11 changes: 10 additions & 1 deletion charts/jaeger-postgresql/values-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ database:
url: "postgresql://postgres:password@localhost:5432/jaeger"
maxConns: 10

# -- (object) Source database url from a secret
urlFromSecret:
# name of secret
# name: ""
# key within secret containing url
# key: ""

service:
logLevel: "info"

Expand Down Expand Up @@ -107,4 +114,6 @@ cleaner:

tolerations: []

affinity: {}
affinity: {}

extraEnvs: []
86 changes: 62 additions & 24 deletions cmd/jaeger-postgresql-cleaner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,33 @@ package main

import (
"context"
"flag"
"fmt"
"io/fs"
"log/slog"
"strings"
"time"

"github.com/jackc/pgx/v5/pgtype"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/robbert229/jaeger-postgresql/internal/logger"
"github.com/robbert229/jaeger-postgresql/internal/sql"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"go.uber.org/fx"
"go.uber.org/fx/fxevent"
)

var (
databaseURLFlag = flag.String("database.url", "", "the postgres connection url to use to connect to the database")
databaseMaxConnsFlag = flag.Int("database.max-conns", 20, "Max number of database connections of which the plugin will try to maintain at any given time")
loglevelFlag = flag.String("log-level", "warn", "Minimal allowed log level")
maxSpanAgeFlag = flag.Duration("max-span-age", time.Hour*24, "Maximum age of a span before it will be cleaned")
)

// ProvideLogger returns a function that provides a logger
func ProvideLogger() any {
return func() (*slog.Logger, error) {
return logger.New(loglevelFlag)
return func(cfg Config) (*slog.Logger, error) {
return logger.New(&cfg.LogLevel)
}
}

// ProvidePgxPool returns a function that provides a pgx pool
func ProvidePgxPool() any {
return func(logger *slog.Logger, lc fx.Lifecycle) (*pgxpool.Pool, error) {
if databaseURLFlag == nil {
return nil, fmt.Errorf("invalid database url")
}

databaseURL := *databaseURLFlag
return func(cfg Config, logger *slog.Logger, lc fx.Lifecycle) (*pgxpool.Pool, error) {
databaseURL := cfg.Database.URL
if databaseURL == "" {
return nil, fmt.Errorf("invalid database url")
}
Expand All @@ -54,10 +46,10 @@ func ProvidePgxPool() any {
// handle max conns
{
var maxConns int32
if databaseMaxConnsFlag == nil {
if cfg.Database.MaxConns == 0 {
maxConns = 20
} else {
maxConns = int32(*databaseMaxConnsFlag)
maxConns = int32(cfg.Database.MaxConns)
}

pgxconfig.MaxConns = maxConns
Expand Down Expand Up @@ -89,33 +81,79 @@ func ProvidePgxPool() any {
}

// clean purges the old roles from the database
func clean(ctx context.Context, pool *pgxpool.Pool) (int64, error) {
func clean(ctx context.Context, pool *pgxpool.Pool, maxAge time.Duration) (int64, error) {
q := sql.New(pool)
result, err := q.CleanSpans(ctx, pgtype.Timestamp{Time: time.Now().Add(-1 * *maxSpanAgeFlag), Valid: true})
result, err := q.CleanSpans(ctx, pgtype.Timestamp{Time: time.Now().Add(-1 * maxAge), Valid: true})
if err != nil {
return 0, err
}

return result, nil
}

func main() {
flag.Parse()
type Config struct {
Database struct {
URL string `mapstructure:"url"`
MaxConns int `mapstructure:"max-conns"`
} `mapstructure:"database"`

LogLevel string `mapstructure:"log-level"`

MaxSpanAge time.Duration `mapstructure:"max-span-age"`
}

func ProvideConfig() func() (Config, error) {
return func() (Config, error) {
pflag.String("database.url", "", "the postgres connection url to use to connect to the database")
pflag.Int("database.max-conns", 20, "Max number of database connections of which the plugin will try to maintain at any given time")
pflag.String("log-level", "warn", "Minimal allowed log level")
pflag.Duration("max-span-age", time.Hour*24, "Maximum age of a span before it will be cleaned")

v := viper.New()
v.SetEnvPrefix("JAEGER_POSTGRESQL")
v.AutomaticEnv()
v.SetConfigFile("jaeger-postgresql")
v.SetConfigType("yaml")
v.AddConfigPath(".")
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
pflag.Parse()
v.BindPFlags(pflag.CommandLine)

var cfg Config
if err := v.ReadInConfig(); err != nil {
_, ok := err.(*fs.PathError)
_, ok2 := err.(viper.ConfigFileNotFoundError)

if !ok && !ok2 {
return cfg, fmt.Errorf("failed to read in config: %w", err)
}
}

err := v.Unmarshal(&cfg)
if err != nil {
return cfg, fmt.Errorf("failed to decode configuration: %w", err)
}

return cfg, nil
}
}

func main() {
fx.New(
fx.WithLogger(func(logger *slog.Logger) fxevent.Logger {
return &fxevent.SlogLogger{Logger: logger.With("component", "uber/fx")}
}),
fx.Provide(
ProvideConfig(),
ProvideLogger(),
ProvidePgxPool(),
),
fx.Invoke(func(pool *pgxpool.Pool, lc fx.Lifecycle, logger *slog.Logger, stopper fx.Shutdowner) error {
fx.Invoke(func(cfg Config, pool *pgxpool.Pool, lc fx.Lifecycle, logger *slog.Logger, stopper fx.Shutdowner) error {
go func(ctx context.Context) {
ctx, cancelFn := context.WithTimeout(ctx, time.Minute)
defer cancelFn()

count, err := clean(ctx, pool)
count, err := clean(ctx, pool, cfg.MaxSpanAge)
if err != nil {
logger.Error("failed to clean database", "err", err)
stopper.Shutdown(fx.ExitCode(1))
Expand Down
Loading