Skip to content

Commit

Permalink
[extension/dbstorage] support for Postgres (#35757)
Browse files Browse the repository at this point in the history
#### Description
Adds support for Postgres, using a test running a Postgresql docker
image.

#### Link to tracking issue
Fixes #35692

#### Testing
Run a postgresql image and test with it.
  • Loading branch information
atoulme authored Nov 5, 2024
1 parent fe474e3 commit 6c471a4
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 10 deletions.
27 changes: 27 additions & 0 deletions .chloggen/postgres_support.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: bug_fix

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: dbstorage

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add postgresql support

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [35692]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
17 changes: 11 additions & 6 deletions extension/storage/dbstorage/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ import (
)

const (
createTable = "create table if not exists %s (key text primary key, value blob)"
getQueryText = "select value from %s where key=?"
setQueryText = "insert into %s(key, value) values(?,?) on conflict(key) do update set value=?"
deleteQueryText = "delete from %s where key=?"
createTableSqlite = "create table if not exists %s (key text primary key, value blob)"
createTable = "create table if not exists %s (key text primary key, value text)"
getQueryText = "select value from %s where key=$1"
setQueryText = "insert into %s(key, value) values($1,$2) on conflict(key) do update set value=$3"
deleteQueryText = "delete from %s where key=$1"
)

type dbStorageClient struct {
Expand All @@ -30,9 +31,13 @@ type dbStorageClient struct {
deleteQuery *sql.Stmt
}

func newClient(ctx context.Context, db *sql.DB, tableName string) (*dbStorageClient, error) {
func newClient(ctx context.Context, driverName string, db *sql.DB, tableName string) (*dbStorageClient, error) {
createTableSQL := createTable
if driverName == "sqlite" {
createTableSQL = createTableSqlite
}
var err error
_, err = db.ExecContext(ctx, fmt.Sprintf(createTable, tableName))
_, err = db.ExecContext(ctx, fmt.Sprintf(createTableSQL, tableName))
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion extension/storage/dbstorage/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (ds *databaseStorage) GetClient(ctx context.Context, kind component.Kind, e
fullName = fmt.Sprintf("%s_%s_%s_%s", kindString(kind), ent.Type(), ent.Name(), name)
}
fullName = strings.ReplaceAll(fullName, " ", "")
return newClient(ctx, ds.db, fullName)
return newClient(ctx, ds.driverName, ds.db, fullName)
}

func kindString(k component.Kind) string {
Expand Down
59 changes: 56 additions & 3 deletions extension/storage/dbstorage/extension_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,28 @@ import (
"sync"
"testing"

ctypes "github.com/docker/docker/api/types/container"
"github.com/docker/go-connections/nat"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/extension/experimental/storage"
"go.opentelemetry.io/collector/extension/extensiontest"
)

func TestExtensionIntegrity(t *testing.T) {
func TestExtensionIntegrityWithSqlite(t *testing.T) {
testExtensionIntegrity(t, newSqliteTestExtension(t))
}

func TestExtensionIntegrityWithPostgres(t *testing.T) {
testExtensionIntegrity(t, newPostgresTestExtension(t))
}

func testExtensionIntegrity(t *testing.T, se storage.Extension) {
ctx := context.Background()
se := newTestExtension(t)
err := se.Start(context.Background(), componenttest.NewNopHost())
assert.NoError(t, err)
defer func() {
Expand Down Expand Up @@ -97,7 +108,7 @@ func TestExtensionIntegrity(t *testing.T) {
wg.Wait()
}

func newTestExtension(t *testing.T) storage.Extension {
func newSqliteTestExtension(t *testing.T) storage.Extension {
f := NewFactory()
cfg := f.CreateDefaultConfig().(*Config)
cfg.DriverName = "sqlite3"
Expand All @@ -112,6 +123,48 @@ func newTestExtension(t *testing.T) storage.Extension {
return se
}

func newPostgresTestExtension(t *testing.T) storage.Extension {
req := testcontainers.GenericContainerRequest{
ContainerRequest: testcontainers.ContainerRequest{
Image: "postgres:14",
HostConfigModifier: func(config *ctypes.HostConfig) {
ports := nat.PortMap{}
ports[nat.Port("5432")] = []nat.PortBinding{
{HostPort: "5432"},
}
config.PortBindings = ports
},
Env: map[string]string{
"POSTGRES_PASSWORD": "passwd",
"POSTGRES_USER": "root",
"POSTGRES_DB": "db",
},
WaitingFor: wait.ForListeningPort("5432"),
},
Started: true,
}

ctr, err := testcontainers.GenericContainer(context.Background(), req)
require.NoError(t, err)
port, err := ctr.MappedPort(context.Background(), "5432")
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, ctr.Terminate(context.Background()))
})
f := NewFactory()
cfg := f.CreateDefaultConfig().(*Config)
cfg.DriverName = "pgx"
cfg.DataSource = fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", "127.0.0.1", port.Port(), "root", "passwd", "db")

extension, err := f.Create(context.Background(), extensiontest.NewNopSettings(), cfg)
require.NoError(t, err)

se, ok := extension.(storage.Extension)
require.True(t, ok)

return se
}

func newTestEntity(name string) component.ID {
return component.MustNewIDWithName("nop", name)
}
35 changes: 35 additions & 0 deletions extension/storage/dbstorage/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ module github.com/open-telemetry/opentelemetry-collector-contrib/extension/stora
go 1.22.0

require (
github.com/docker/docker v27.1.1+incompatible
github.com/docker/go-connections v0.5.0
github.com/jackc/pgx/v5 v5.7.1
github.com/mattn/go-sqlite3 v1.14.24
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go v0.33.0
go.opentelemetry.io/collector/component v0.112.0
go.opentelemetry.io/collector/confmap v1.18.0
go.opentelemetry.io/collector/extension v0.112.0
Expand All @@ -15,23 +18,55 @@ require (
)

require (
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/containerd/containerd v1.7.18 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
github.com/knadh/koanf/v2 v2.1.1 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/shirou/gopsutil/v3 v3.23.12 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.112.0 // indirect
go.opentelemetry.io/collector/pdata v1.18.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.31.0 // indirect
go.opentelemetry.io/otel/metric v1.31.0 // indirect
go.opentelemetry.io/otel/sdk v1.31.0 // indirect
Expand Down
Loading

0 comments on commit 6c471a4

Please sign in to comment.