Skip to content

postgres: postgresql migration to opentelemetry #3552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ require (
github.com/Azure/go-amqp v1.4.0
github.com/Azure/go-autorest/autorest/to v0.4.1
github.com/GoogleCloudPlatform/cloudsql-proxy v1.37.6
github.com/XSAM/otelsql v0.38.0
github.com/aws/aws-sdk-go v1.55.6
github.com/aws/aws-sdk-go-v2 v1.36.3
github.com/aws/aws-sdk-go-v2/config v1.29.12
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0/go.mod h1:SZiPHWGOOk3bl8tkevxkoiwPgsIl6CwrWcbwjfHZpdM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 h1:6/0iUd0xrnX7qt+mLNRwg5c0PGv8wpE8K90ryANQwMI=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0=
github.com/XSAM/otelsql v0.38.0 h1:zWU0/YM9cJhPE71zJcQ2EBHwQDp+G4AX2tPpljslaB8=
github.com/XSAM/otelsql v0.38.0/go.mod h1:5ePOgcLEkWvZtN9H3GV4BUlPeM3p3pzLDCnRG73X8h8=
github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk=
github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
Expand Down
1 change: 1 addition & 0 deletions internal/testing/alldeps
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping
github.com/IBM/sarama
github.com/XSAM/otelsql
github.com/aws/aws-sdk-go
github.com/aws/aws-sdk-go-v2
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream
Expand Down
46 changes: 22 additions & 24 deletions postgres/awspostgres/awspostgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ import (
"net/url"
"time"

"contrib.go.opencensus.io/integrations/ocsql"
"github.com/XSAM/otelsql"
"github.com/lib/pq"
"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
"gocloud.dev/aws/rds"
"gocloud.dev/postgres"
)
Expand All @@ -49,8 +51,6 @@ type URLOpener struct {
// CertSource specifies how the opener will obtain the RDS Certificate
// Authority. If nil, it will use the default *rds.CertFetcher.
CertSource rds.CertPoolProvider
// TraceOpts contains options for OpenCensus.
TraceOpts []ocsql.TraceOption
}

// Scheme is the URL scheme awspostgres registers its URLOpener under on
Expand All @@ -61,7 +61,7 @@ func init() {
postgres.DefaultURLMux().RegisterPostgres(Scheme, &URLOpener{})
}

// OpenPostgresURL opens a new RDS database connection wrapped with OpenCensus instrumentation.
// OpenPostgresURL opens a new RDS database connection wrapped with OpenTelemetry instrumentation.
func (uo *URLOpener) OpenPostgresURL(ctx context.Context, u *url.URL) (*sql.DB, error) {
source := uo.CertSource
if source == nil {
Expand All @@ -82,17 +82,20 @@ func (uo *URLOpener) OpenPostgresURL(ctx context.Context, u *url.URL) (*sql.DB,
*u2 = *u
u2.Scheme = "postgres"
u2.RawQuery = query.Encode()
db := sql.OpenDB(connector{
provider: source,
pqConn: u2.String(),
traceOpts: append([]ocsql.TraceOption(nil), uo.TraceOpts...),
})
// Use github.com/XSAM/otelsql directly for OpenTelemetry instrumentation
connector := &pqConnector{provider: source, pqConn: u2.String()}
db := otelsql.OpenDB(connector,
otelsql.WithAttributes(
semconv.DBSystemKey.String("postgresql"),
semconv.DBNameKey.String("postgres"),
attribute.String("service.name", "go-cloud-awspostgres"),
attribute.String("cloud.provider", "aws"),
))
return db, nil
}

type pqDriver struct {
provider rds.CertPoolProvider
traceOpts []ocsql.TraceOption
provider rds.CertPoolProvider
}

func (d pqDriver) Open(name string) (driver.Conn, error) {
Expand All @@ -101,25 +104,20 @@ func (d pqDriver) Open(name string) (driver.Conn, error) {
}

func (d pqDriver) OpenConnector(name string) (driver.Connector, error) {
return connector{d.provider, name + " sslmode=disable", d.traceOpts}, nil
return &pqConnector{d.provider, name + " sslmode=disable"}, nil
}

type connector struct {
provider rds.CertPoolProvider
pqConn string
traceOpts []ocsql.TraceOption
type pqConnector struct {
provider rds.CertPoolProvider
pqConn string
}

func (c connector) Connect(context.Context) (driver.Conn, error) {
conn, err := pq.DialOpen(dialer{c.provider}, c.pqConn)
if err != nil {
return nil, err
}
return ocsql.WrapConn(conn, c.traceOpts...), nil
func (c *pqConnector) Connect(ctx context.Context) (driver.Conn, error) {
return pq.DialOpen(dialer{c.provider}, c.pqConn)
}

func (c connector) Driver() driver.Driver {
return pqDriver{c.provider, c.traceOpts}
func (c *pqConnector) Driver() driver.Driver {
return pqDriver{c.provider}
}

type dialer struct {
Expand Down
54 changes: 27 additions & 27 deletions postgres/gcppostgres/gcppostgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ import (
"sync"
"time"

"contrib.go.opencensus.io/integrations/ocsql"
"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/proxy"
"github.com/XSAM/otelsql"
"github.com/lib/pq"
"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
"gocloud.dev/gcp"
"gocloud.dev/gcp/cloudsql"
"gocloud.dev/postgres"
Expand Down Expand Up @@ -90,12 +92,9 @@ type URLOpener struct {
// CertSource specifies how the opener will obtain authentication information.
// CertSource must not be nil.
CertSource proxy.CertSource

// TraceOpts contains options for OpenCensus.
TraceOpts []ocsql.TraceOption
}

// OpenPostgresURL opens a new GCP database connection wrapped with OpenCensus instrumentation.
// OpenPostgresURL opens a new GCP database connection wrapped with OpenTelemetry instrumentation.
func (uo *URLOpener) OpenPostgresURL(ctx context.Context, u *url.URL) (*sql.DB, error) {
if uo.CertSource == nil {
return nil, fmt.Errorf("gcppostgres: URLOpener CertSource is nil")
Expand All @@ -120,15 +119,22 @@ func (uo *URLOpener) OpenPostgresURL(ctx context.Context, u *url.URL) (*sql.DB,
u2.Host = "cloudsql"
u2.Path = "/" + dbName
u2.RawQuery = query.Encode()
db := sql.OpenDB(connector{
// Use github.com/XSAM/otelsql directly for OpenTelemetry instrumentation
connector := &pqConnector{
client: &proxy.Client{
Port: 3307,
Certs: uo.CertSource,
},
instance: instance,
pqConn: u2.String(),
traceOpts: append([]ocsql.TraceOption(nil), uo.TraceOpts...),
})
instance: instance,
pqConn: u2.String(),
}
db := otelsql.OpenDB(connector,
otelsql.WithAttributes(
semconv.DBSystemKey.String("postgresql"),
semconv.DBNameKey.String("postgres"),
attribute.String("service.name", "go-cloud-gcppostgres"),
attribute.String("cloud.provider", "gcp"),
))
return db, nil
}

Expand All @@ -147,9 +153,8 @@ func instanceFromURL(u *url.URL) (instance, db string, _ error) {
}

type pqDriver struct {
client *proxy.Client
instance string
traceOpts []ocsql.TraceOption
client *proxy.Client
instance string
}

func (d pqDriver) Open(name string) (driver.Conn, error) {
Expand All @@ -158,26 +163,21 @@ func (d pqDriver) Open(name string) (driver.Conn, error) {
}

func (d pqDriver) OpenConnector(name string) (driver.Connector, error) {
return connector{d.client, d.instance, name, d.traceOpts}, nil
return &pqConnector{d.client, d.instance, name}, nil
}

type connector struct {
client *proxy.Client
instance string
pqConn string
traceOpts []ocsql.TraceOption
type pqConnector struct {
client *proxy.Client
instance string
pqConn string
}

func (c connector) Connect(context.Context) (driver.Conn, error) {
conn, err := pq.DialOpen(dialer{c.client, c.instance}, c.pqConn)
if err != nil {
return nil, err
}
return ocsql.WrapConn(conn, c.traceOpts...), nil
func (c *pqConnector) Connect(ctx context.Context) (driver.Conn, error) {
return pq.DialOpen(dialer{c.client, c.instance}, c.pqConn)
}

func (c connector) Driver() driver.Driver {
return pqDriver{c.client, c.instance, c.traceOpts}
func (c *pqConnector) Driver() driver.Driver {
return pqDriver{c.client, c.instance}
}

type dialer struct {
Expand Down
22 changes: 16 additions & 6 deletions postgres/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Package postgres provides functions to open PostgreSQL databases with OpenCensus instrumentation.
// Package postgres provides functions to open PostgreSQL databases with OpenTelemetry instrumentation.
package postgres

import (
Expand All @@ -21,10 +21,11 @@ import (
"database/sql/driver"
"net/url"

"github.com/XSAM/otelsql"
"github.com/lib/pq"
"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
"gocloud.dev/internal/openurl"

"contrib.go.opencensus.io/integrations/ocsql"
)

// Scheme is the URL scheme this package registers its URLOpener under on
Expand All @@ -39,12 +40,20 @@ func init() {
// See https://godoc.org/github.com/lib/pq#hdr-Connection_String_Parameters for details.
type URLOpener struct{}

// OpenPostgresURL opens a new database connection wrapped with OpenCensus instrumentation.
// OpenPostgresURL opens a new database connection wrapped with OpenTelemetry instrumentation.
func (*URLOpener) OpenPostgresURL(ctx context.Context, u *url.URL) (*sql.DB, error) {
u2 := new(url.URL)
*u2 = *u
u2.Scheme = "postgres"
return sql.OpenDB(connector{dsn: u2.String()}), nil

// Use github.com/XSAM/otelsql directly for OpenTelemetry instrumentation
return otelsql.Open("postgres", u2.String(),
otelsql.WithAttributes(
semconv.DBSystemKey.String("postgresql"),
semconv.DBNameKey.String("postgres"),
attribute.String("service.name", "go-cloud-postgres"),
),
)
}

type connector struct {
Expand All @@ -56,7 +65,8 @@ func (c connector) Connect(ctx context.Context) (driver.Conn, error) {
}

func (c connector) Driver() driver.Driver {
return ocsql.Wrap(&pq.Driver{})
// Direct OpenTelemetry driver registration happens in otelsql.Open
return &pq.Driver{}
}

// PostgresURLOpener can open Postgres connections based on a URL.
Expand Down