Unistore Chore: add inocuous preparative changes for otel-based db observability (#94473)

add inocuous preparative changes for otel tracing
This commit is contained in:
Diego Augusto Molina
2024-10-09 20:32:09 +00:00
committed by GitHub
parent 8349db4947
commit 4a800eda9f
9 changed files with 936 additions and 119 deletions
@@ -9,11 +9,10 @@ import (
"github.com/go-sql-driver/mysql"
"xorm.io/xorm"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/storage/unified/sql/db"
)
func getEngineMySQL(getter confGetter, tracer tracing.Tracer) (*xorm.Engine, error) {
func getEngineMySQL(getter confGetter) (*xorm.Engine, error) {
config := mysql.NewConfig()
config.User = getter.String("user")
// accept the core Grafana jargon of `password` as well, originally Unified
@@ -54,8 +53,6 @@ func getEngineMySQL(getter confGetter, tracer tracing.Tracer) (*xorm.Engine, err
}
// FIXME: get rid of xorm
// TODO figure out why wrapping the db driver with hooks causes mysql errors when writing
//driverName := sqlstore.WrapDatabaseDriverWithHooks(db.DriverMySQL, tracer)
engine, err := xorm.NewEngine(db.DriverMySQL, config.FormatDSN())
if err != nil {
return nil, fmt.Errorf("open database: %w", err)
@@ -68,7 +65,7 @@ func getEngineMySQL(getter confGetter, tracer tracing.Tracer) (*xorm.Engine, err
return engine, nil
}
func getEnginePostgres(getter confGetter, tracer tracing.Tracer) (*xorm.Engine, error) {
func getEnginePostgres(getter confGetter) (*xorm.Engine, error) {
dsnKV := map[string]string{
"user": getter.String("user"),
// accept the core Grafana jargon of `password` as well, originally
@@ -25,14 +25,14 @@ func TestGetEngineMySQLFromConfig(t *testing.T) {
t.Run("happy path - with key prefix", func(t *testing.T) {
t.Parallel()
engine, err := getEngineMySQL(newValidMySQLGetter(true), nil)
engine, err := getEngineMySQL(newValidMySQLGetter(true))
assert.NotNil(t, engine)
assert.NoError(t, err)
})
t.Run("happy path - without key prefix", func(t *testing.T) {
t.Parallel()
engine, err := getEngineMySQL(newValidMySQLGetter(false), nil)
engine, err := getEngineMySQL(newValidMySQLGetter(false))
assert.NotNil(t, engine)
assert.NoError(t, err)
})
@@ -47,7 +47,7 @@ func TestGetEngineMySQLFromConfig(t *testing.T) {
"db_user": "user",
"db_password": "password",
}, "db_")
engine, err := getEngineMySQL(getter, nil)
engine, err := getEngineMySQL(getter)
assert.Nil(t, engine)
assert.Error(t, err)
assert.ErrorIs(t, err, errInvalidUTF8Sequence)
@@ -73,14 +73,14 @@ func TestGetEnginePostgresFromConfig(t *testing.T) {
t.Run("happy path - with key prefix", func(t *testing.T) {
t.Parallel()
engine, err := getEnginePostgres(newValidPostgresGetter(true), nil)
engine, err := getEnginePostgres(newValidPostgresGetter(true))
assert.NotNil(t, engine)
assert.NoError(t, err)
})
t.Run("happy path - without key prefix", func(t *testing.T) {
t.Parallel()
engine, err := getEnginePostgres(newValidPostgresGetter(false), nil)
engine, err := getEnginePostgres(newValidPostgresGetter(false))
assert.NotNil(t, engine)
assert.NoError(t, err)
})
@@ -94,7 +94,7 @@ func TestGetEnginePostgresFromConfig(t *testing.T) {
"db_user": "user",
"db_password": "password",
}, "db_")
engine, err := getEnginePostgres(getter, nil)
engine, err := getEnginePostgres(getter)
assert.Nil(t, engine)
assert.Error(t, err)
@@ -110,7 +110,7 @@ func TestGetEnginePostgresFromConfig(t *testing.T) {
"db_user": "user",
"db_password": "password",
}, "db_")
engine, err := getEnginePostgres(getter, nil)
engine, err := getEnginePostgres(getter)
assert.Nil(t, engine)
assert.Error(t, err)
+6 -5
View File
@@ -9,6 +9,7 @@ import (
"github.com/dlmiddlecote/sqlstats"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/otel/trace"
"xorm.io/xorm"
infraDB "github.com/grafana/grafana/pkg/infra/db"
@@ -63,7 +64,7 @@ type resourceDBProvider struct {
logQueries bool
}
func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer tracing.Tracer) (p *resourceDBProvider, err error) {
func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer trace.Tracer) (p *resourceDBProvider, err error) {
// Resource API has other configs in its section besides database ones, so
// we prefix them with "db_". We use the database config from core Grafana
// as fallback, and as it uses a dedicated INI section, then keys are not
@@ -85,12 +86,12 @@ func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer tracin
// specific to Unified Storage
case dbType == dbTypePostgres:
p.registerMetrics = true
p.engine, err = getEnginePostgres(getter, tracer)
p.engine, err = getEnginePostgres(getter)
return p, err
case dbType == dbTypeMySQL:
p.registerMetrics = true
p.engine, err = getEngineMySQL(getter, tracer)
p.engine, err = getEngineMySQL(getter)
return p, err
// TODO: add support for SQLite
@@ -103,12 +104,12 @@ func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer tracin
case grafanaDBType == dbTypePostgres:
p.registerMetrics = true
p.engine, err = getEnginePostgres(fallbackGetter, tracer)
p.engine, err = getEnginePostgres(fallbackGetter)
return p, err
case grafanaDBType == dbTypeMySQL:
p.registerMetrics = true
p.engine, err = getEngineMySQL(fallbackGetter, tracer)
p.engine, err = getEngineMySQL(fallbackGetter)
return p, err
// TODO: add support for SQLite
@@ -0,0 +1,95 @@
package dbimpl
import (
"context"
"database/sql"
"database/sql/driver"
"sync"
)
var _ driver.Driver = driverWithoutIsolationLevel{}
var _ driver.Driver = driverWithIsolationLevel{}
const (
driverWithoutIsolationLevelName = "test driver without isolation levels"
driverWithIsolationLevelName = "test driver with isolation levels"
)
var registerTestDriversOnce sync.Once
func registerTestSQLDrivers() {
registerTestDriversOnce.Do(func() {
sql.Register(driverWithoutIsolationLevelName, driverWithoutIsolationLevel{})
sql.Register(driverWithIsolationLevelName, driverWithIsolationLevel{})
})
}
type (
// without isolation level
driverWithoutIsolationLevel struct{}
connWithoutIsolationLevel struct{}
// with isolation level
driverWithIsolationLevel struct{}
connWithIsolationLevel struct {
connWithoutIsolationLevel
}
// common
testStmt struct{}
testTx struct{}
testResults struct{}
testRows struct{}
)
// driver.Driver
func (driverWithoutIsolationLevel) Open(name string) (driver.Conn, error) {
return connWithoutIsolationLevel{}, nil
}
func (driverWithIsolationLevel) Open(name string) (driver.Conn, error) {
return connWithIsolationLevel{}, nil
}
// driver.Conn
func (connWithoutIsolationLevel) Prepare(query string) (driver.Stmt, error) {
return testStmt{}, nil
}
func (connWithoutIsolationLevel) Close() error {
return nil
}
func (connWithoutIsolationLevel) Begin() (driver.Tx, error) {
return testTx{}, nil
}
func (connWithIsolationLevel) BeginTx(context.Context, driver.TxOptions) (driver.Tx, error) {
return testTx{}, nil
}
// driver.Stmt
func (testStmt) Close() error { return nil }
func (testStmt) NumInput() int { return 0 }
func (testStmt) Exec(args []driver.Value) (driver.Result, error) { return testResults{}, nil }
func (testStmt) Query(args []driver.Value) (driver.Rows, error) { return testRows{}, nil }
// driver.Tx
func (testTx) Commit() error { return nil }
func (testTx) Rollback() error { return nil }
// driver.Results
func (testResults) LastInsertId() (int64, error) { return 1, nil }
func (testResults) RowsAffected() (int64, error) { return 1, nil }
// driver.Rows
func (testRows) Columns() []string { return nil }
func (testRows) Close() error { return nil }
func (testRows) Next(dest []driver.Value) error { return nil }
@@ -1,10 +1,7 @@
package dbimpl
import (
"context"
"database/sql"
"database/sql/driver"
"sync"
"testing"
"github.com/stretchr/testify/require"
@@ -16,93 +13,6 @@ import (
const noIsolationLevelSupportErrStr = "sql: driver does not support non-" +
"default isolation level"
var _ driver.Driver = driverWithoutIsolationLevel{}
var _ driver.Driver = driverWithIsolationLevel{}
const (
driverWithoutIsolationLevelName = "test driver without isolation levels"
driverWithIsolationLevelName = "test driver with isolation levels"
)
var registerTestDriversOnce sync.Once
func registerTestSQLDrivers() {
registerTestDriversOnce.Do(func() {
sql.Register(driverWithoutIsolationLevelName, driverWithoutIsolationLevel{})
sql.Register(driverWithIsolationLevelName, driverWithIsolationLevel{})
})
}
type (
// without isolation level
driverWithoutIsolationLevel struct{}
connWithoutIsolationLevel struct{}
// with isolation level
driverWithIsolationLevel struct{}
connWithIsolationLevel struct {
connWithoutIsolationLevel
}
// common
testStmt struct{}
testTx struct{}
testResults struct{}
testRows struct{}
)
// driver.Driver
func (driverWithoutIsolationLevel) Open(name string) (driver.Conn, error) {
return connWithoutIsolationLevel{}, nil
}
func (driverWithIsolationLevel) Open(name string) (driver.Conn, error) {
return connWithIsolationLevel{}, nil
}
// driver.Conn
func (connWithoutIsolationLevel) Prepare(query string) (driver.Stmt, error) {
return testStmt{}, nil
}
func (connWithoutIsolationLevel) Close() error {
return nil
}
func (connWithoutIsolationLevel) Begin() (driver.Tx, error) {
return testTx{}, nil
}
func (connWithIsolationLevel) BeginTx(context.Context, driver.TxOptions) (driver.Tx, error) {
return testTx{}, nil
}
// driver.Stmt
func (testStmt) Close() error { return nil }
func (testStmt) NumInput() int { return 0 }
func (testStmt) Exec(args []driver.Value) (driver.Result, error) { return testResults{}, nil }
func (testStmt) Query(args []driver.Value) (driver.Rows, error) { return testRows{}, nil }
// driver.Tx
func (testTx) Commit() error { return nil }
func (testTx) Rollback() error { return nil }
// driver.Results
func (testResults) LastInsertId() (int64, error) { return 1, nil }
func (testResults) RowsAffected() (int64, error) { return 1, nil }
// driver.Rows
func (testRows) Columns() []string { return nil }
func (testRows) Close() error { return nil }
func (testRows) Next(dest []driver.Value) error { return nil }
func TestReproIncident2144IndependentOfGrafanaDB(t *testing.T) {
t.Parallel()
registerTestSQLDrivers()