db

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2026 License: MIT Imports: 21 Imported by: 0

README

Database Package

Multi-database support with GORM, automated migrations, and OpenTelemetry instrumentation.

Overview

The db package provides a unified interface for connecting to multiple database systems with automatic OpenTelemetry tracing and metrics collection. Built on GORM and golang-migrate, it simplifies database operations while providing production-ready observability.

Features

  • Multi-Database Support: PostgreSQL, MySQL, MSSQL
  • GORM Integration: Full ORM capabilities with GORM v2
  • Automatic Tracing: Query-level distributed tracing
  • Connection Pool Metrics: Real-time pool health monitoring
  • Schema Migrations: Embedded migrations with golang-migrate
  • Type-Safe Configuration: Validation with struct tags
  • Zero Configuration OTel: Optional but seamless observability
  • Fluent Builder Pattern: Chain configuration methods for clean setup

Installation

go get github.com/davidsugianto/go-pkgs/db

Quick Start

Basic Connection
package main

import (
    "context"
    "log"
    "time"

    "github.com/davidsugianto/go-pkgs/db"
)

func main() {
    ctx := context.Background()

    // Create config with fluent builder pattern
    config := db.NewConfig(db.Postgres, "localhost", "myapp").
        WithPort(5432).
        WithCredentials("postgres", "password").
        WithPool(25, 5, 5*time.Minute, 10*time.Minute)

    client, err := db.New(ctx, config)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    // Verify connection
    if err := client.Ping(ctx); err != nil {
        log.Fatal(err)
    }
}
Using Options Pattern
client, err := db.New(ctx,
    db.NewConfig(db.MySQL, "localhost", "myapp"),
    db.WithPort(3306),
    db.WithCredentials("root", "password"),
    db.WithTracing(true),
    db.WithMetricsOption(true),
)

Configuration

Fluent Builder Methods
config := db.NewConfig(db.Postgres, "localhost", "mydb").
    WithPort(5432).                              // Set custom port
    WithCredentials("user", "pass").             // Set username/password
    WithSSL("require", "cert.pem", "key.pem", "root.pem").  // SSL config
    WithPool(50, 10, 10*time.Minute, 20*time.Minute).       // Pool settings
    WithTracing(true).                           // Enable OTel tracing
    WithMetrics(true)                            // Enable OTel metrics
Configuration Struct
type Config struct {
    Type     string // postgres, mysql, mssql
    Host     string
    Port     int
    Username string
    Password string
    Database string

    // SSL
    SSLMode     string
    SSLCert     string
    SSLKey      string
    SSLRootCert string

    // Pool
    MaxOpenConns    int
    MaxIdleConns    int
    ConnMaxLifetime time.Duration
    ConnMaxIdleTime time.Duration

    // OpenTelemetry
    EnableTracing bool
    EnableMetrics bool
}

Database Operations

Auto Migration
type User struct {
    ID        uint      `gorm:"primaryKey"`
    Name      string    `gorm:"size:100;not null"`
    Email     string    `gorm:"size:255;uniqueIndex"`
    CreatedAt time.Time
}

if err := client.DB.AutoMigrate(&User{}); err != nil {
    log.Fatal(err)
}
Transactions
err := client.Transaction(ctx, func(tx *gorm.DB) error {
    user := User{Name: "John", Email: "john@example.com"}
    if err := tx.Create(&user).Error; err != nil {
        return err
    }
    return nil
})
Context Propagation
// Use WithContext for request-scoped operations
var users []User
if err := client.WithContext(ctx).Find(&users).Error; err != nil {
    log.Fatal(err)
}
Health Check
if client.IsHealthy(ctx) {
    fmt.Println("Database is healthy!")
}
Connection Pool Stats
stats, err := client.Stats()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Open: %d, InUse: %d, Idle: %d\n",
    stats.OpenConnections, stats.InUse, stats.Idle)

Schema Migrations

Embedded Migrations
//go:embed migrations/*.sql
var migrationsFS embed.FS

// Run migrations
if err := client.Migrate(ctx, migrationsFS, "migrations"); err != nil {
    log.Fatal(err)
}
Migration File Structure
migrations/
├── 000001_init.up.sql
├── 000001_init.down.sql
├── 000002_add_users.up.sql
└── 000002_add_users.down.sql

OpenTelemetry Integration

Automatic Tracing

When EnableTracing is true, all database operations are automatically traced:

config := db.NewConfig(db.Postgres, "localhost", "myapp").
    WithTracing(true)
Connection Pool Metrics

When EnableMetrics is true, pool metrics are collected:

config := db.NewConfig(db.Postgres, "localhost", "myapp").
    WithMetrics(true)

Metrics exposed:

  • db.connection.pool.size - Connection counts by state (max, open, in_use, idle, wait_count)

Supported Databases

Database Type Constant Default Port
PostgreSQL db.Postgres 5432
MySQL db.MySQL 3306
MSSQL db.MSSQL 1433

Error Handling

import "errors"

client, err := db.New(ctx, config)
if errors.Is(err, db.ErrInvalidDatabaseType) {
    // Handle invalid database type
}
if errors.Is(err, db.ErrConnectionFailed) {
    // Handle connection failure
}
if errors.Is(err, db.ErrMigrationFailed) {
    // Handle migration failure
}

Example

See example/main.go for a complete working example.

Dependencies

  • gorm.io/gorm - ORM
  • gorm.io/driver/postgres - PostgreSQL driver
  • gorm.io/driver/mysql - MySQL driver
  • gorm.io/driver/sqlserver - MSSQL driver
  • gorm.io/plugin/opentelemetry/tracing - OTel tracing plugin
  • github.com/golang-migrate/migrate/v4 - Schema migrations
  • go.opentelemetry.io/otel - OpenTelemetry SDK

License

MIT

Documentation

Index

Constants

View Source
const (
	Postgres = "postgres"
	MySQL    = "mysql"
	MSSQL    = "mssql"
)

Database type constants

Variables

View Source
var (
	ErrInvalidDatabaseType = errors.New("invalid database type")
	ErrConnectionFailed    = errors.New("connection failed")
	ErrMigrationFailed     = errors.New("migration failed")
)

Functions

This section is empty.

Types

type Client

type Client struct {
	*gorm.DB
	// contains filtered or unexported fields
}

Client wraps gorm.DB with additional functionality

func MustNew

func MustNew(ctx context.Context, config *Config, opts ...Option) *Client

MustNew creates a new database client or panics on error

func New

func New(ctx context.Context, config *Config, opts ...Option) (*Client, error)

New creates a new database client

func (*Client) Close

func (c *Client) Close() error

Close closes the database connection

func (*Client) IsHealthy

func (c *Client) IsHealthy(ctx context.Context) bool

IsHealthy checks if the database connection is healthy

func (*Client) Migrate

func (c *Client) Migrate(ctx context.Context, migrationsFS embed.FS, migrationsPath string) error

Migrate runs database migrations using embedded migration files

func (*Client) MigrationVersion

func (c *Client) MigrationVersion() (uint, bool, error)

MigrationVersion returns the current migration version

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping verifies the database connection

func (*Client) Stats

func (c *Client) Stats() (*sql.DBStats, error)

Stats returns connection pool statistics

func (*Client) Transaction

func (c *Client) Transaction(ctx context.Context, fn func(tx *gorm.DB) error) error

Transaction executes a function within a database transaction

func (*Client) WithContext

func (c *Client) WithContext(ctx context.Context) *Client

WithContext returns a new client with the given context

type Config

type Config struct {
	// Database type (postgres, mysql, mssql)
	Type string `json:"type" yaml:"type" validate:"required,oneof=postgres mysql mssql"`

	// Connection settings
	Host     string `json:"host" yaml:"host" validate:"required"`
	Port     int    `json:"port" yaml:"port" validate:"required,min=1,max=65535"`
	Username string `json:"username" yaml:"username"`
	Password string `json:"password" yaml:"password"`
	Database string `json:"database" yaml:"database" validate:"required"`

	// SSL settings
	SSLMode     string `json:"ssl_mode" yaml:"ssl_mode"`           // for postgres: disable, require, verify-ca, verify-full
	SSLCert     string `json:"ssl_cert" yaml:"ssl_cert"`           // path to cert file
	SSLKey      string `json:"ssl_key" yaml:"ssl_key"`             // path to key file
	SSLRootCert string `json:"ssl_root_cert" yaml:"ssl_root_cert"` // path to root cert file

	// Connection pool settings
	MaxOpenConns    int           `json:"max_open_conns" yaml:"max_open_conns"`
	MaxIdleConns    int           `json:"max_idle_conns" yaml:"max_idle_conns"`
	ConnMaxLifetime time.Duration `json:"conn_max_lifetime" yaml:"conn_max_lifetime"`
	ConnMaxIdleTime time.Duration `json:"conn_max_idle_time" yaml:"conn_max_idle_time"`

	// OpenTelemetry settings
	EnableTracing bool `json:"enable_tracing" yaml:"enable_tracing"`
	EnableMetrics bool `json:"enable_metrics" yaml:"enable_metrics"`

	// GORM settings
	SkipDefaultTransaction bool `json:"skip_default_transaction" yaml:"skip_default_transaction"`
	PrepareStmt            bool `json:"prepare_stmt" yaml:"prepare_stmt"`
}

Config holds database connection configuration

func NewConfig

func NewConfig(dbType, host, database string) *Config

NewConfig creates a new Config with defaults

func (*Config) WithCredentials

func (c *Config) WithCredentials(username, password string) *Config

WithCredentials sets the username and password

func (*Config) WithMetrics

func (c *Config) WithMetrics(enabled bool) *Config

WithMetrics enables or disables OpenTelemetry metrics

func (*Config) WithPool

func (c *Config) WithPool(maxOpen, maxIdle int, maxLifetime, maxIdleTime time.Duration) *Config

WithPool sets connection pool settings

func (*Config) WithPort

func (c *Config) WithPort(port int) *Config

WithPort sets the database port

func (*Config) WithSSL

func (c *Config) WithSSL(mode, cert, key, rootCert string) *Config

WithSSL sets SSL configuration

func (*Config) WithTracing

func (c *Config) WithTracing(enabled bool) *Config

WithTracing enables or disables OpenTelemetry tracing

type Option

type Option func(*Config)

Option configures the database client

func WithCredentials

func WithCredentials(username, password string) Option

WithCredentials sets the username and password (as Option for functional options pattern)

func WithMetricsOption

func WithMetricsOption(enabled bool) Option

WithMetrics enables or disables OpenTelemetry metrics (as Option for functional options pattern)

func WithPool

func WithPool(maxOpen, maxIdle int, maxLifetime, maxIdleTime time.Duration) Option

WithPool sets connection pool settings (as Option for functional options pattern)

func WithPort

func WithPort(port int) Option

WithPort sets the database port (as Option for functional options pattern)

func WithSSL

func WithSSL(mode, cert, key, rootCert string) Option

WithSSL sets SSL configuration (as Option for functional options pattern)

func WithTracing

func WithTracing(enabled bool) Option

WithTracing enables or disables OpenTelemetry tracing (as Option for functional options pattern)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL