feat(pgsql): implement application_name handling in connection
This commit is contained in:
85
pkg/pgsql/connection.go
Normal file
85
pkg/pgsql/connection.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package pgsql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultApplicationPrefix = "relspecgo"
|
||||
postgresIdentifierMaxLen = 63
|
||||
)
|
||||
|
||||
// BuildApplicationName returns a PostgreSQL application_name in the form:
|
||||
// relspecgo/<version>[:<component>]
|
||||
func BuildApplicationName(component string) string {
|
||||
appName := fmt.Sprintf("%s/%s", defaultApplicationPrefix, relspecVersion())
|
||||
component = strings.TrimSpace(component)
|
||||
if component != "" {
|
||||
appName = appName + ":" + component
|
||||
}
|
||||
if len(appName) > postgresIdentifierMaxLen {
|
||||
appName = appName[:postgresIdentifierMaxLen]
|
||||
}
|
||||
return appName
|
||||
}
|
||||
|
||||
// ParseConfigWithApplicationName parses a connection string and applies a default
|
||||
// application_name when one is not explicitly provided by the caller.
|
||||
func ParseConfigWithApplicationName(connString, component string) (*pgx.ConnConfig, error) {
|
||||
cfg, err := pgx.ParseConfig(connString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg.RuntimeParams == nil {
|
||||
cfg.RuntimeParams = map[string]string{}
|
||||
}
|
||||
|
||||
if strings.TrimSpace(cfg.RuntimeParams["application_name"]) == "" {
|
||||
cfg.RuntimeParams["application_name"] = BuildApplicationName(component)
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// Connect establishes a PostgreSQL connection with a default relspec
|
||||
// application_name when the caller does not provide one in the DSN.
|
||||
func Connect(ctx context.Context, connString, component string) (*pgx.Conn, error) {
|
||||
cfg, err := ParseConfigWithApplicationName(connString, component)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pgx.ConnectConfig(ctx, cfg)
|
||||
}
|
||||
|
||||
func relspecVersion() string {
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return "dev"
|
||||
}
|
||||
|
||||
version := strings.TrimSpace(info.Main.Version)
|
||||
if version != "" && version != "(devel)" {
|
||||
return version
|
||||
}
|
||||
|
||||
for _, setting := range info.Settings {
|
||||
if setting.Key == "vcs.revision" {
|
||||
revision := strings.TrimSpace(setting.Value)
|
||||
if len(revision) >= 7 {
|
||||
return revision[:7]
|
||||
}
|
||||
if revision != "" {
|
||||
return revision
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "dev"
|
||||
}
|
||||
Reference in New Issue
Block a user