Unistore: Reuse MySQL and Postgres Grafana core config instead of the object (#94223)
* Reuse MySQL and Postgres Grafana config instead of the object - Only reuse the Grafana DB object for SQLite. Support for SQLite will be added in a different PR - Fail when reusing the Grafana DB object if it is using DB instrumentation - In the case that we have to reuse a Grafana DB with its instrumentation, fail with an error that describes a workaround - Add regression tests to reproduce incident 2144 * remove temp file * fix linter * fix linter x2 * fix linter x3
This commit is contained in:
committed by
GitHub
parent
a82f102878
commit
7d32d5eff4
@@ -2,6 +2,7 @@ package dbimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
@@ -12,7 +13,6 @@ import (
|
||||
|
||||
infraDB "github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/sql/db"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/sql/db/migrations"
|
||||
@@ -23,8 +23,17 @@ const (
|
||||
dbTypePostgres = "postgres"
|
||||
)
|
||||
|
||||
func ProvideResourceDB(grafanaDB infraDB.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, tracer tracing.Tracer) (db.DBProvider, error) {
|
||||
p, err := newResourceDBProvider(grafanaDB, cfg, features, tracer)
|
||||
const grafanaDBInstrumentQueriesKey = "instrument_queries"
|
||||
|
||||
var errGrafanaDBInstrumentedNotSupported = errors.New("the Resource API is " +
|
||||
"attempting to leverage the database from core Grafana defined in the" +
|
||||
" [database] INI section since a database configuration was not provided" +
|
||||
" in the [resource_api] section. But we detected that the key `" +
|
||||
grafanaDBInstrumentQueriesKey + "` is enabled in [database], and that" +
|
||||
" setup is currently unsupported. Please, consider disabling that flag")
|
||||
|
||||
func ProvideResourceDB(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer tracing.Tracer) (db.DBProvider, error) {
|
||||
p, err := newResourceDBProvider(grafanaDB, cfg, tracer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("provide Resource DB: %w", err)
|
||||
}
|
||||
@@ -54,41 +63,67 @@ type resourceDBProvider struct {
|
||||
logQueries bool
|
||||
}
|
||||
|
||||
func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, tracer tracing.Tracer) (p *resourceDBProvider, err error) {
|
||||
// TODO: This should be renamed resource_api
|
||||
getter := §ionGetter{
|
||||
DynamicSection: cfg.SectionWithEnvOverrides("resource_api"),
|
||||
}
|
||||
func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer tracing.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
|
||||
// prefixed with "db_"
|
||||
getter := newConfGetter(cfg.SectionWithEnvOverrides("resource_api"), "db_")
|
||||
fallbackGetter := newConfGetter(cfg.SectionWithEnvOverrides("database"), "")
|
||||
|
||||
p = &resourceDBProvider{
|
||||
cfg: cfg,
|
||||
log: log.New("entity-db"),
|
||||
logQueries: getter.Key("log_queries").MustBool(false),
|
||||
logQueries: getter.Bool("log_queries"),
|
||||
migrateFunc: migrations.MigrateResourceStore,
|
||||
}
|
||||
|
||||
switch dbType := getter.Key("db_type").MustString(""); dbType {
|
||||
case dbTypePostgres:
|
||||
dbType := getter.String("type")
|
||||
grafanaDBType := fallbackGetter.String("type")
|
||||
switch {
|
||||
// First try with the config in the "resource_api" section, which is
|
||||
// specific to Unified Storage
|
||||
case dbType == dbTypePostgres:
|
||||
p.registerMetrics = true
|
||||
p.engine, err = getEnginePostgres(getter, tracer)
|
||||
return p, err
|
||||
|
||||
case dbTypeMySQL:
|
||||
case dbType == dbTypeMySQL:
|
||||
p.registerMetrics = true
|
||||
p.engine, err = getEngineMySQL(getter, tracer)
|
||||
return p, err
|
||||
|
||||
case "":
|
||||
// TODO: add support for SQLite
|
||||
|
||||
case dbType != "":
|
||||
return p, fmt.Errorf("invalid db type specified: %s", dbType)
|
||||
|
||||
// If we have an empty Resource API db config, try with the core Grafana
|
||||
// database config
|
||||
|
||||
case grafanaDBType == dbTypePostgres:
|
||||
p.registerMetrics = true
|
||||
p.engine, err = getEnginePostgres(fallbackGetter, tracer)
|
||||
return p, err
|
||||
|
||||
case grafanaDBType == dbTypeMySQL:
|
||||
p.registerMetrics = true
|
||||
p.engine, err = getEngineMySQL(fallbackGetter, tracer)
|
||||
return p, err
|
||||
|
||||
// TODO: add support for SQLite
|
||||
|
||||
case grafanaDB != nil:
|
||||
// try to use the grafana db connection
|
||||
if grafanaDB == nil {
|
||||
return p, fmt.Errorf("no db connection provided")
|
||||
|
||||
if fallbackGetter.Bool(grafanaDBInstrumentQueriesKey) {
|
||||
return nil, errGrafanaDBInstrumentedNotSupported
|
||||
}
|
||||
p.engine = grafanaDB.GetEngine()
|
||||
return p, nil
|
||||
|
||||
default:
|
||||
// TODO: sqlite support
|
||||
return p, fmt.Errorf("invalid db type specified: %s", dbType)
|
||||
return p, fmt.Errorf("no db connection provided")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +137,6 @@ func (p *resourceDBProvider) init(ctx context.Context) (db.DB, error) {
|
||||
_ = p.logQueries // TODO: configure SQL logging
|
||||
|
||||
// TODO: change the migrator to use db.DB instead of xorm
|
||||
// Skip migrations if feature flag is not enabled
|
||||
if p.migrateFunc != nil {
|
||||
err := p.migrateFunc(ctx, p.engine, p.cfg)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user