diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c57de4578db0..5395976652bd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -126,6 +126,7 @@ internal/kubelet/ @open-telemetry/collect internal/metadataproviders/ @open-telemetry/collector-contrib-approvers @Aneurysm9 @dashpole internal/sharedcomponent/ @open-telemetry/collector-contrib-approvers @open-telemetry/collector-approvers internal/splunk/ @open-telemetry/collector-contrib-approvers @dmitryax +internal/sqlquery/ @open-telemetry/collector-contrib-approvers @crobert-1 @dmitryax internal/tools/ @open-telemetry/collector-contrib-approvers pkg/batchperresourceattr/ @open-telemetry/collector-contrib-approvers @atoulme @dmitryax diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 4e9ac1cf1b89..d3c35ae45fe0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -124,6 +124,7 @@ body: - internal/metadataproviders - internal/sharedcomponent - internal/splunk + - internal/sqlquery - internal/tools - pkg/batchperresourceattr - pkg/batchpersignal diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index e2120c8364f2..e8b8e3016828 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -118,6 +118,7 @@ body: - internal/metadataproviders - internal/sharedcomponent - internal/splunk + - internal/sqlquery - internal/tools - pkg/batchperresourceattr - pkg/batchpersignal diff --git a/.github/ISSUE_TEMPLATE/other.yaml b/.github/ISSUE_TEMPLATE/other.yaml index 09c9202dc031..cf03cb515b3e 100644 --- a/.github/ISSUE_TEMPLATE/other.yaml +++ b/.github/ISSUE_TEMPLATE/other.yaml @@ -118,6 +118,7 @@ body: - internal/metadataproviders - internal/sharedcomponent - internal/splunk + - internal/sqlquery - internal/tools - pkg/batchperresourceattr - pkg/batchpersignal diff --git a/cmd/configschema/go.mod b/cmd/configschema/go.mod index 7cb9641de4aa..569248d75ca8 100644 --- a/cmd/configschema/go.mod +++ b/cmd/configschema/go.mod @@ -77,6 +77,7 @@ require ( github.com/open-telemetry/opentelemetry-collector-contrib/internal/kubelet v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/internal/splunk v0.93.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchperresourceattr v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.93.0 // indirect @@ -1150,3 +1151,5 @@ replace ( github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector => ../../connector/servicegraphconnector github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector => ../../connector/spanmetricsconnector ) + +replace github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery => ../../internal/sqlquery diff --git a/cmd/otelcontribcol/builder-config.yaml b/cmd/otelcontribcol/builder-config.yaml index 146195c85780..dcbb93e1385a 100644 --- a/cmd/otelcontribcol/builder-config.yaml +++ b/cmd/otelcontribcol/builder-config.yaml @@ -453,3 +453,4 @@ replaces: - github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampextension => ../../extension/opampextension - github.com/open-telemetry/opentelemetry-collector-contrib/extension/solarwindsapmsettingsextension => ../../extension/solarwindsapmsettingsextension - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/namedpipereceiver => ../../receiver/namedpipereceiver + - github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery => ../../internal/sqlquery diff --git a/cmd/otelcontribcol/go.mod b/cmd/otelcontribcol/go.mod index a5402c45e964..485897d16b08 100644 --- a/cmd/otelcontribcol/go.mod +++ b/cmd/otelcontribcol/go.mod @@ -547,6 +547,7 @@ require ( github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/internal/splunk v0.93.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchperresourceattr v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/experimentalmetricmetadata v0.93.0 // indirect @@ -1191,3 +1192,5 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/extension/opam replace github.com/open-telemetry/opentelemetry-collector-contrib/extension/solarwindsapmsettingsextension => ../../extension/solarwindsapmsettingsextension replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/namedpipereceiver => ../../receiver/namedpipereceiver + +replace github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery => ../../internal/sqlquery diff --git a/go.mod b/go.mod index a4d385e68fdc..d59e68002fcc 100644 --- a/go.mod +++ b/go.mod @@ -516,6 +516,7 @@ require ( github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/internal/splunk v0.93.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchperresourceattr v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.93.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/pkg/experimentalmetricmetadata v0.93.0 // indirect @@ -1151,3 +1152,5 @@ replace ( github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector => ./connector/servicegraphconnector github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector => ./connector/spanmetricsconnector ) + +replace github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery => ./internal/sqlquery diff --git a/internal/sqlquery/Makefile b/internal/sqlquery/Makefile new file mode 100644 index 000000000000..ded7a36092dc --- /dev/null +++ b/internal/sqlquery/Makefile @@ -0,0 +1 @@ +include ../../Makefile.Common diff --git a/internal/sqlquery/config.go b/internal/sqlquery/config.go new file mode 100644 index 000000000000..d45fbf4a9960 --- /dev/null +++ b/internal/sqlquery/config.go @@ -0,0 +1,178 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" + +import ( + "errors" + "fmt" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/receiver/scraperhelper" + "go.uber.org/multierr" +) + +type Config struct { + scraperhelper.ScraperControllerSettings `mapstructure:",squash"` + Driver string `mapstructure:"driver"` + DataSource string `mapstructure:"datasource"` + Queries []Query `mapstructure:"queries"` + StorageID *component.ID `mapstructure:"storage"` + Telemetry TelemetryConfig `mapstructure:"telemetry"` +} + +func (c Config) Validate() error { + if c.Driver == "" { + return errors.New("'driver' cannot be empty") + } + if c.DataSource == "" { + return errors.New("'datasource' cannot be empty") + } + if len(c.Queries) == 0 { + return errors.New("'queries' cannot be empty") + } + for _, query := range c.Queries { + if err := query.Validate(); err != nil { + return err + } + } + return nil +} + +type Query struct { + SQL string `mapstructure:"sql"` + Metrics []MetricCfg `mapstructure:"metrics"` + Logs []LogsCfg `mapstructure:"logs"` + TrackingColumn string `mapstructure:"tracking_column"` + TrackingStartValue string `mapstructure:"tracking_start_value"` +} + +func (q Query) Validate() error { + var errs error + if q.SQL == "" { + errs = multierr.Append(errs, errors.New("'query.sql' cannot be empty")) + } + if len(q.Logs) == 0 && len(q.Metrics) == 0 { + errs = multierr.Append(errs, errors.New("at least one of 'query.logs' and 'query.metrics' must not be empty")) + } + for _, logs := range q.Logs { + if err := logs.Validate(); err != nil { + errs = multierr.Append(errs, err) + } + } + for _, metric := range q.Metrics { + if err := metric.Validate(); err != nil { + errs = multierr.Append(errs, err) + } + } + return errs +} + +type LogsCfg struct { + BodyColumn string `mapstructure:"body_column"` +} + +func (config LogsCfg) Validate() error { + var errs error + if config.BodyColumn == "" { + errs = multierr.Append(errs, errors.New("'body_column' must not be empty")) + } + return errs +} + +type MetricCfg struct { + MetricName string `mapstructure:"metric_name"` + ValueColumn string `mapstructure:"value_column"` + AttributeColumns []string `mapstructure:"attribute_columns"` + Monotonic bool `mapstructure:"monotonic"` + ValueType MetricValueType `mapstructure:"value_type"` + DataType MetricType `mapstructure:"data_type"` + Aggregation MetricAggregation `mapstructure:"aggregation"` + Unit string `mapstructure:"unit"` + Description string `mapstructure:"description"` + StaticAttributes map[string]string `mapstructure:"static_attributes"` + StartTsColumn string `mapstructure:"start_ts_column"` + TsColumn string `mapstructure:"ts_column"` +} + +func (c MetricCfg) Validate() error { + var errs error + if c.MetricName == "" { + errs = multierr.Append(errs, errors.New("'metric_name' cannot be empty")) + } + if c.ValueColumn == "" { + errs = multierr.Append(errs, errors.New("'value_column' cannot be empty")) + } + if err := c.ValueType.Validate(); err != nil { + errs = multierr.Append(errs, err) + } + if err := c.DataType.Validate(); err != nil { + errs = multierr.Append(errs, err) + } + if err := c.Aggregation.Validate(); err != nil { + errs = multierr.Append(errs, err) + } + if c.DataType == MetricTypeGauge && c.Aggregation != "" { + errs = multierr.Append(errs, fmt.Errorf("aggregation=%s but data_type=%s does not support aggregation", c.Aggregation, c.DataType)) + } + if errs != nil && c.MetricName != "" { + errs = multierr.Append(fmt.Errorf("invalid metric config with metric_name '%s'", c.MetricName), errs) + } + return errs +} + +type MetricType string + +const ( + MetricTypeUnspecified MetricType = "" + MetricTypeGauge MetricType = "gauge" + MetricTypeSum MetricType = "sum" +) + +func (t MetricType) Validate() error { + switch t { + case MetricTypeUnspecified, MetricTypeGauge, MetricTypeSum: + return nil + } + return fmt.Errorf("metric config has unsupported data_type: '%s'", t) +} + +type MetricValueType string + +const ( + MetricValueTypeUnspecified MetricValueType = "" + MetricValueTypeInt MetricValueType = "int" + MetricValueTypeDouble MetricValueType = "double" +) + +func (t MetricValueType) Validate() error { + switch t { + case MetricValueTypeUnspecified, MetricValueTypeInt, MetricValueTypeDouble: + return nil + } + return fmt.Errorf("metric config has unsupported value_type: '%s'", t) +} + +type MetricAggregation string + +const ( + MetricAggregationUnspecified MetricAggregation = "" + MetricAggregationCumulative MetricAggregation = "cumulative" + MetricAggregationDelta MetricAggregation = "delta" +) + +func (a MetricAggregation) Validate() error { + switch a { + case MetricAggregationUnspecified, MetricAggregationCumulative, MetricAggregationDelta: + return nil + } + return fmt.Errorf("metric config has unsupported aggregation: '%s'", a) +} + +type TelemetryConfig struct { + Logs TelemetryLogsConfig `mapstructure:"logs"` +} + +type TelemetryLogsConfig struct { + Query bool `mapstructure:"query"` +} diff --git a/internal/sqlquery/db_client.go b/internal/sqlquery/db_client.go new file mode 100644 index 000000000000..9f7d00908f0f --- /dev/null +++ b/internal/sqlquery/db_client.go @@ -0,0 +1,93 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" + +import ( + "context" + + // register Db drivers + _ "github.com/SAP/go-hdb/driver" + _ "github.com/go-sql-driver/mysql" + _ "github.com/lib/pq" + _ "github.com/microsoft/go-mssqldb" + _ "github.com/microsoft/go-mssqldb/integratedauth/krb5" + _ "github.com/sijms/go-ora/v2" + _ "github.com/snowflakedb/gosnowflake" + "go.uber.org/multierr" + "go.uber.org/zap" +) + +type StringMap map[string]string + +type DbClient interface { + QueryRows(ctx context.Context, args ...any) ([]StringMap, error) +} + +type DbSQLClient struct { + Db Db + Logger *zap.Logger + Telemetry TelemetryConfig + SQL string +} + +func NewDbClient(db Db, sql string, logger *zap.Logger, telemetry TelemetryConfig) DbClient { + return DbSQLClient{ + Db: db, + SQL: sql, + Logger: logger, + Telemetry: telemetry, + } +} + +func (cl DbSQLClient) QueryRows(ctx context.Context, args ...any) ([]StringMap, error) { + cl.Logger.Debug("Running query", cl.prepareQueryFields(cl.SQL, args)...) + sqlRows, err := cl.Db.QueryContext(ctx, cl.SQL, args...) + if err != nil { + return nil, err + } + var out []StringMap + colTypes, err := sqlRows.ColumnTypes() + if err != nil { + return nil, err + } + scanner := newRowScanner(colTypes) + var warnings error + for sqlRows.Next() { + err = scanner.scan(sqlRows) + if err != nil { + return nil, err + } + sm, scanErr := scanner.toStringMap() + if scanErr != nil { + warnings = multierr.Append(warnings, scanErr) + } + out = append(out, sm) + } + return out, warnings +} + +func (cl DbSQLClient) prepareQueryFields(sql string, args []any) []zap.Field { + var logFields []zap.Field + if cl.Telemetry.Logs.Query { + logFields = append(logFields, zap.String("query", sql)) + logFields = append(logFields, zap.Any("parameters", args)) + } + return logFields +} + +// This is only used for testing, but need to be exposed to other packages. +type FakeDBClient struct { + RequestCounter int + StringMaps [][]StringMap + Err error +} + +func (c *FakeDBClient) QueryRows(context.Context, ...any) ([]StringMap, error) { + if c.Err != nil { + return nil, c.Err + } + idx := c.RequestCounter + c.RequestCounter++ + return c.StringMaps[idx], nil +} diff --git a/receiver/sqlqueryreceiver/db_client_test.go b/internal/sqlquery/db_client_test.go similarity index 72% rename from receiver/sqlqueryreceiver/db_client_test.go rename to internal/sqlquery/db_client_test.go index 4fb591c68be4..a40ebd02e31f 100644 --- a/receiver/sqlqueryreceiver/db_client_test.go +++ b/internal/sqlquery/db_client_test.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package sqlqueryreceiver +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" import ( "context" @@ -16,12 +16,12 @@ import ( ) func TestDBSQLClient_SingleRow(t *testing.T) { - cl := dbSQLClient{ - db: fakeDB{rowVals: [][]any{{42, 123.4, "hello", true, []uint8{52, 46, 49}}}}, - logger: zap.NewNop(), - sql: "", + cl := DbSQLClient{ + Db: fakeDB{rowVals: [][]any{{42, 123.4, "hello", true, []uint8{52, 46, 49}}}}, + Logger: zap.NewNop(), + SQL: "", } - rows, err := cl.queryRows(context.Background()) + rows, err := cl.QueryRows(context.Background()) require.NoError(t, err) assert.Len(t, rows, 1) assert.EqualValues(t, map[string]string{ @@ -34,15 +34,15 @@ func TestDBSQLClient_SingleRow(t *testing.T) { } func TestDBSQLClient_MultiRow(t *testing.T) { - cl := dbSQLClient{ - db: fakeDB{rowVals: [][]any{ + cl := DbSQLClient{ + Db: fakeDB{rowVals: [][]any{ {42, 123.4, "hello", true, []uint8{52, 46, 49}}, {43, 123.5, "goodbye", false, []uint8{52, 46, 50}}, }}, - logger: zap.NewNop(), - sql: "", + Logger: zap.NewNop(), + SQL: "", } - rows, err := cl.queryRows(context.Background()) + rows, err := cl.QueryRows(context.Background()) require.NoError(t, err) assert.Len(t, rows, 2) assert.EqualValues(t, map[string]string{ @@ -62,14 +62,14 @@ func TestDBSQLClient_MultiRow(t *testing.T) { } func TestDBSQLClient_Nulls(t *testing.T) { - cl := dbSQLClient{ - db: fakeDB{rowVals: [][]any{ + cl := DbSQLClient{ + Db: fakeDB{rowVals: [][]any{ {42, nil, 111}, // NULLs from the DB map to nil here }}, - logger: zap.NewNop(), - sql: "", + Logger: zap.NewNop(), + SQL: "", } - rows, err := cl.queryRows(context.Background()) + rows, err := cl.QueryRows(context.Background()) assert.Error(t, err) assert.True(t, errors.Is(err, errNullValueWarning)) assert.Len(t, rows, 1) @@ -80,15 +80,15 @@ func TestDBSQLClient_Nulls(t *testing.T) { } func TestDBSQLClient_Nulls_MultiRow(t *testing.T) { - cl := dbSQLClient{ - db: fakeDB{rowVals: [][]any{ + cl := DbSQLClient{ + Db: fakeDB{rowVals: [][]any{ {42, nil}, {43, nil}, }}, - logger: zap.NewNop(), - sql: "", + Logger: zap.NewNop(), + SQL: "", } - rows, err := cl.queryRows(context.Background()) + rows, err := cl.QueryRows(context.Background()) assert.Error(t, err) errs := multierr.Errors(err) for _, err := range errs { @@ -145,18 +145,3 @@ type fakeCol struct { func (c fakeCol) Name() string { return c.name } - -type fakeDBClient struct { - requestCounter int - stringMaps [][]stringMap - err error -} - -func (c *fakeDBClient) queryRows(context.Context, ...any) ([]stringMap, error) { - if c.err != nil { - return nil, c.err - } - idx := c.requestCounter - c.requestCounter++ - return c.stringMaps[idx], nil -} diff --git a/receiver/sqlqueryreceiver/db_wrappers.go b/internal/sqlquery/db_wrappers.go similarity index 73% rename from receiver/sqlqueryreceiver/db_wrappers.go rename to internal/sqlquery/db_wrappers.go index 5c8d88073afd..a8b788c82dd8 100644 --- a/receiver/sqlqueryreceiver/db_wrappers.go +++ b/internal/sqlquery/db_wrappers.go @@ -1,16 +1,16 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package sqlqueryreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver" +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" import ( "context" "database/sql" ) -// These are wrappers and interfaces around sql.DB so that it can be swapped out for testing. +// These are wrappers and interfaces around SQL.DB so that it can be swapped out for testing. -type db interface { +type Db interface { QueryContext(ctx context.Context, query string, args ...any) (rows, error) } @@ -24,12 +24,12 @@ type colType interface { Name() string } -type dbWrapper struct { - db *sql.DB +type DbWrapper struct { + Db *sql.DB } -func (d dbWrapper) QueryContext(ctx context.Context, query string, args ...any) (rows, error) { - rows, err := d.db.QueryContext(ctx, query, args...) +func (d DbWrapper) QueryContext(ctx context.Context, query string, args ...any) (rows, error) { + rows, err := d.Db.QueryContext(ctx, query, args...) return rowsWrapper{rows}, err } diff --git a/internal/sqlquery/go.mod b/internal/sqlquery/go.mod new file mode 100644 index 000000000000..6f6f9b313482 --- /dev/null +++ b/internal/sqlquery/go.mod @@ -0,0 +1,111 @@ +module github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery + +go 1.20 + +require ( + github.com/SAP/go-hdb v1.7.7 + github.com/go-sql-driver/mysql v1.7.1 + github.com/lib/pq v1.10.9 + github.com/microsoft/go-mssqldb v1.6.0 + github.com/sijms/go-ora/v2 v2.8.6 + github.com/snowflakedb/gosnowflake v1.7.2 + github.com/stretchr/testify v1.8.4 + go.opentelemetry.io/collector/component v0.93.1-0.20240130182548-89388addcc7f + go.opentelemetry.io/collector/pdata v1.0.2-0.20240130181942-9c7177496fd5 + go.opentelemetry.io/collector/receiver v0.93.1-0.20240130182548-89388addcc7f + go.uber.org/multierr v1.11.0 + go.uber.org/zap v1.26.0 +) + +require ( + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 // indirect + github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect + github.com/apache/arrow/go/v14 v14.0.2 // indirect + github.com/aws/aws-sdk-go-v2 v1.17.7 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.18 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 // indirect + github.com/aws/smithy-go v1.13.5 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect + github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect + github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/flatbuffers v23.5.26+incompatible // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/jcmturner/aescts/v2 v2.0.0 // indirect + github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect + github.com/jcmturner/gofork v1.7.6 // indirect + github.com/jcmturner/goidentity/v6 v6.0.1 // indirect + github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect + github.com/jcmturner/rpc/v2 v2.0.3 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // 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.0.1 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/pierrec/lz4/v4 v4.1.18 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.18.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.46.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/zeebo/xxh3 v1.0.2 // indirect + go.opentelemetry.io/collector v0.93.1-0.20240130182548-89388addcc7f // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.93.1-0.20240130182548-89388addcc7f // indirect + go.opentelemetry.io/collector/confmap v0.93.1-0.20240130182548-89388addcc7f // indirect + go.opentelemetry.io/collector/consumer v0.93.1-0.20240130182548-89388addcc7f // indirect + go.opentelemetry.io/otel v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.45.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/sdk v1.22.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.22.0 // indirect + go.opentelemetry.io/otel/trace v1.22.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.17.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/grpc v1.61.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/internal/sqlquery/go.sum b/internal/sqlquery/go.sum new file mode 100644 index 000000000000..554cdd09e397 --- /dev/null +++ b/internal/sqlquery/go.sum @@ -0,0 +1,321 @@ +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= +github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0 h1:HCc0+LpPfpCKs6LGGLAhwBARt9632unrVcI6i8s/8os= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/SAP/go-hdb v1.7.7 h1:yA/KE5ozzHfPrPlOf7yAPUwbFGrJXBcdnBkQwUKG/VE= +github.com/SAP/go-hdb v1.7.7/go.mod h1:P56UwOZO7QpDS0wyEWFPSxtyjwwbFBs3eFuOU/TSCvk= +github.com/apache/arrow/go/v14 v14.0.2 h1:N8OkaJEOfI3mEZt07BIkvo4sC6XDbL+48MBPWO5IONw= +github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY= +github.com/aws/aws-sdk-go-v2 v1.17.7 h1:CLSjnhJSTSogvqUGhIC6LqFKATMRexcxLZ0i/Nzk9Eg= +github.com/aws/aws-sdk-go-v2 v1.17.7/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= +github.com/aws/aws-sdk-go-v2/config v1.18.19 h1:AqFK6zFNtq4i1EYu+eC7lcKHYnZagMn6SW171la0bGw= +github.com/aws/aws-sdk-go-v2/config v1.18.19/go.mod h1:XvTmGMY8d52ougvakOv1RpiTLPz9dlG/OQHsKU/cMmY= +github.com/aws/aws-sdk-go-v2/credentials v1.13.18 h1:EQMdtHwz0ILTW1hoP+EwuWhwCG1hD6l3+RWFQABET4c= +github.com/aws/aws-sdk-go-v2/credentials v1.13.18/go.mod h1:vnwlwjIe+3XJPBYKu1et30ZPABG3VaXJYr8ryohpIyM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 h1:gt57MN3liKiyGopcqgNzJb2+d9MJaKT/q1OksHNXVE4= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1/go.mod h1:lfUx8puBRdM5lVVMQlwt2v+ofiG/X6Ms+dy0UkG/kXw= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59 h1:E3Y+OfzOK1+rmRo/K2G0ml8Vs+Xqk0kOnf4nS0kUtBc= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59/go.mod h1:1M4PLSBUVfBI0aP+C9XI7SM6kZPCGYyI6izWz0TGprE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 h1:sJLYcS+eZn5EeNINGHSCRAwUJMFVqklwkH36Vbyai7M= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31/go.mod h1:QT0BqUvX1Bh2ABdTGnjqEjvjzrCfIniM9Sc8zn9Yndo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 h1:1mnRASEKnkqsntcxHaysxwgVoUUp5dkiB+l3llKnqyg= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25/go.mod h1:zBHOPwhBc3FlQjQJE/D3IfPWiWaQmT06Vq9aNukDo0k= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 h1:p5luUImdIqywn6JpQsW3tq5GNOxKmOnEpybzPx+d1lk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32/go.mod h1:XGhIBZDEgfqmFIugclZ6FU7v75nHhBDtzuB4xB/tEi4= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 h1:DWYZIsyqagnWL00f8M/SOr9fN063OEQWn9LLTbdYXsk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23/go.mod h1:uIiFgURZbACBEQJfqTZPb/jxO7R+9LeoHUFudtIdeQI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 h1:CeuSeq/8FnYpPtnuIeLQEEvDv9zUjneuYi8EghMBdwQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26/go.mod h1:2UqAAwMUXKeRkAHIlDJqvMVgOWkUi/AUXPk/YIe+Dg4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 h1:5LHn8JQ0qvjD9L9JhMtylnkcw7j05GDZqM9Oin6hpr0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25/go.mod h1:/95IA+0lMnzW6XzqYJRpjjsAbKEORVeO0anQqjd2CNU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 h1:e2ooMhpYGhDnBfSvIyusvAwX7KexuZaHbQY2Dyei7VU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0/go.mod h1:bh2E0CXKZsQN+faiKVqC40vfNMAWheoULBCnEgO9K+8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 h1:B1G2pSPvbAtQjilPq+Y7jLIzCOwKzuVEl+aBBaNG0AQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0/go.mod h1:ncltU6n4Nof5uJttDtcNQ537uNuwYqsZZQcpkd2/GUQ= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 h1:5V7DWLBd7wTELVz5bPpwzYy/sikk0gsgZfj40X+l5OI= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.6/go.mod h1:Y1VOmit/Fn6Tz1uFAeCO6Q7M2fmfXSCLeL5INVYsLuY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 h1:B8cauxOH1W1v7rd8RdI/MWnoR4Ze0wIHWrb90qczxj4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6/go.mod h1:Lh/bc9XUf8CfOY6Jp5aIkQtN+j1mc+nExc+KXj9jx2s= +github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 h1:bWNgNdRko2x6gqa0blfATqAZKZokPIeM1vfmQt2pnvM= +github.com/aws/aws-sdk-go-v2/service/sts v1.18.7/go.mod h1:JuTnSoeePXmMVe9G8NcjjwgOKEfZ4cOjMuT2IBT/2eI= +github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8= +github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= +github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= +github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= +github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU= +github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= +github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc= +github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= +github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/sijms/go-ora/v2 v2.8.6 h1:sq907Z5cno0YIXidOYM85tiQFFVhhgssw09IJPG0WG4= +github.com/sijms/go-ora/v2 v2.8.6/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/snowflakedb/gosnowflake v1.7.2 h1:HRSwva8YXC64WUppfmHcMNVVzSE1+EwXXaJxgS0EkTo= +github.com/snowflakedb/gosnowflake v1.7.2/go.mod h1:03tW856vc3ceM4rJuj7KO4dzqN7qoezTm+xw7aPIIFo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.opentelemetry.io/collector v0.93.1-0.20240130182548-89388addcc7f h1:NgQcLNPP/6YnIfNUkDkKu1uiRTXUa9kMtfpsKSVC4dY= +go.opentelemetry.io/collector v0.93.1-0.20240130182548-89388addcc7f/go.mod h1:rEqeAsOy8Mu6HA6oMjGk7NrTb7958XmShSaapxFEeTs= +go.opentelemetry.io/collector/component v0.93.1-0.20240130182548-89388addcc7f h1:DNFOx9vwV7g+lWz9htP/Biiwwp+oFifR+J2zKnQKV3U= +go.opentelemetry.io/collector/component v0.93.1-0.20240130182548-89388addcc7f/go.mod h1:jOHaBlhWt4aarDS6w9A9GcgGCxrtEg+8LnBK7Y/6zqo= +go.opentelemetry.io/collector/config/configtelemetry v0.93.1-0.20240130182548-89388addcc7f h1:S1mp1jVnxg0tyy7uFEMHDFRqI4AiqqE/ia8RPj3SKW0= +go.opentelemetry.io/collector/config/configtelemetry v0.93.1-0.20240130182548-89388addcc7f/go.mod h1:2XLhyR/GVpWeZ2K044vCmrvH/d4Ewt0aD/y46avZyMU= +go.opentelemetry.io/collector/confmap v0.93.1-0.20240130182548-89388addcc7f h1:HIvqzK7ANxcVRhtJ/zUm+ZWGHlGo7TClqcaNMwQgzHs= +go.opentelemetry.io/collector/confmap v0.93.1-0.20240130182548-89388addcc7f/go.mod h1:KjHrfxKKojaLDc9zDPfVuyp8765AH+XfcoPWMLMiuHU= +go.opentelemetry.io/collector/consumer v0.93.1-0.20240130182548-89388addcc7f h1:xtOtkpXNP7x+CmP5hpIVNOkfPUQQbWlsjSNUUlczfrE= +go.opentelemetry.io/collector/consumer v0.93.1-0.20240130182548-89388addcc7f/go.mod h1:RhC4X/bSMIENk68hzFS9i6I7DVsZSfF/S7JvfaqZkkI= +go.opentelemetry.io/collector/pdata v1.0.2-0.20240130181942-9c7177496fd5 h1:cMc7sJ29OzK5jZqr6XFzKxiJvlypR/zt2TDhPDqpBic= +go.opentelemetry.io/collector/pdata v1.0.2-0.20240130181942-9c7177496fd5/go.mod h1:IDkDj+B4Fp4wWOclBELN97zcb98HugJ8Q2gA4ZFsN8Q= +go.opentelemetry.io/collector/receiver v0.93.1-0.20240130182548-89388addcc7f h1:2C2QYMLF6YrRJPT/9LhRmfJ0wwF8nt4LjBblBCEJZtM= +go.opentelemetry.io/collector/receiver v0.93.1-0.20240130182548-89388addcc7f/go.mod h1:bPAxjHDsXFJZKPAturS7Ar5DDY/HJz5sj73E72vSVqk= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/exporters/prometheus v0.45.0 h1:BeIK2KGho0oCWa7LxEGSqfDZbs7Fpv/Viz+FS4P8CXE= +go.opentelemetry.io/otel/exporters/prometheus v0.45.0/go.mod h1:UVJZPLnfDSvHj+eJuZE+E1GjIBD267mEMfAAHJdghWg= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/sdk/metric v1.22.0 h1:ARrRetm1HCVxq0cbnaZQlfwODYJHo3gFL8Z3tSmHBcI= +go.opentelemetry.io/otel/sdk/metric v1.22.0/go.mod h1:KjQGeMIDlBNEOo6HvjhxIec1p/69/kULDcp4gr0oLQQ= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.12.0 h1:xKuo6hzt+gMav00meVPUlXwSdoEJP46BR+wdxQEFK2o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/sqlquery/metadata.yaml b/internal/sqlquery/metadata.yaml new file mode 100644 index 000000000000..eab1270e4726 --- /dev/null +++ b/internal/sqlquery/metadata.yaml @@ -0,0 +1,3 @@ +status: + codeowners: + active: [crobert-1, dmitryax] diff --git a/receiver/sqlqueryreceiver/metrics.go b/internal/sqlquery/metrics.go similarity index 95% rename from receiver/sqlqueryreceiver/metrics.go rename to internal/sqlquery/metrics.go index 52799c67bdb7..4a00e3b6269d 100644 --- a/receiver/sqlqueryreceiver/metrics.go +++ b/internal/sqlquery/metrics.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package sqlqueryreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver" +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" import ( "fmt" @@ -12,7 +12,7 @@ import ( "go.opentelemetry.io/collector/receiver/scraperhelper" ) -func rowToMetric(row stringMap, cfg MetricCfg, dest pmetric.Metric, startTime pcommon.Timestamp, ts pcommon.Timestamp, scrapeCfg scraperhelper.ScraperControllerSettings) error { +func rowToMetric(row StringMap, cfg MetricCfg, dest pmetric.Metric, startTime pcommon.Timestamp, ts pcommon.Timestamp, scrapeCfg scraperhelper.ScraperControllerSettings) error { dest.SetName(cfg.MetricName) dest.SetDescription(cfg.Description) dest.SetUnit(cfg.Unit) diff --git a/receiver/sqlqueryreceiver/metrics_test.go b/internal/sqlquery/metrics_test.go similarity index 82% rename from receiver/sqlqueryreceiver/metrics_test.go rename to internal/sqlquery/metrics_test.go index 2af66008a435..d5d46746a9ea 100644 --- a/receiver/sqlqueryreceiver/metrics_test.go +++ b/internal/sqlquery/metrics_test.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package sqlqueryreceiver +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" import ( "testing" diff --git a/receiver/sqlqueryreceiver/row_scanner.go b/internal/sqlquery/row_scanner.go similarity index 88% rename from receiver/sqlqueryreceiver/row_scanner.go rename to internal/sqlquery/row_scanner.go index 99c71ac0299a..9ed0711dc97e 100644 --- a/receiver/sqlqueryreceiver/row_scanner.go +++ b/internal/sqlquery/row_scanner.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package sqlqueryreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver" +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" import ( "errors" @@ -52,8 +52,8 @@ func (rs *rowScanner) scan(sqlRows rows) error { return sqlRows.Scan(rs.scanTarget...) } -func (rs *rowScanner) toStringMap() (stringMap, error) { - out := stringMap{} +func (rs *rowScanner) toStringMap() (StringMap, error) { + out := StringMap{} var errs error for k, f := range rs.cols { s, err := f() diff --git a/internal/sqlquery/scraper.go b/internal/sqlquery/scraper.go new file mode 100644 index 000000000000..e43edf4aea34 --- /dev/null +++ b/internal/sqlquery/scraper.go @@ -0,0 +1,107 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" + +import ( + "context" + "database/sql" + "errors" + "fmt" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver/scrapererror" + "go.opentelemetry.io/collector/receiver/scraperhelper" + "go.uber.org/multierr" + "go.uber.org/zap" +) + +type SQLOpenerFunc func(driverName, dataSourceName string) (*sql.DB, error) + +type DbProviderFunc func() (*sql.DB, error) + +type ClientProviderFunc func(Db, string, *zap.Logger, TelemetryConfig) DbClient + +type Scraper struct { + id component.ID + Query Query + ScrapeCfg scraperhelper.ScraperControllerSettings + StartTime pcommon.Timestamp + ClientProviderFunc ClientProviderFunc + DbProviderFunc DbProviderFunc + Logger *zap.Logger + Telemetry TelemetryConfig + Client DbClient + Db *sql.DB +} + +var _ scraperhelper.Scraper = (*Scraper)(nil) + +func NewScraper(id component.ID, query Query, scrapeCfg scraperhelper.ScraperControllerSettings, logger *zap.Logger, telemetry TelemetryConfig, dbProviderFunc DbProviderFunc, clientProviderFunc ClientProviderFunc) *Scraper { + return &Scraper{ + id: id, + Query: query, + ScrapeCfg: scrapeCfg, + Logger: logger, + Telemetry: telemetry, + DbProviderFunc: dbProviderFunc, + ClientProviderFunc: clientProviderFunc, + } +} + +func (s *Scraper) ID() component.ID { + return s.id +} + +func (s *Scraper) Start(context.Context, component.Host) error { + var err error + s.Db, err = s.DbProviderFunc() + if err != nil { + return fmt.Errorf("failed to open Db connection: %w", err) + } + s.Client = s.ClientProviderFunc(DbWrapper{s.Db}, s.Query.SQL, s.Logger, s.Telemetry) + s.StartTime = pcommon.NewTimestampFromTime(time.Now()) + + return nil +} + +func (s *Scraper) Scrape(ctx context.Context) (pmetric.Metrics, error) { + out := pmetric.NewMetrics() + rows, err := s.Client.QueryRows(ctx) + if err != nil { + if errors.Is(err, errNullValueWarning) { + s.Logger.Warn("problems encountered getting metric rows", zap.Error(err)) + } else { + return out, fmt.Errorf("Scraper: %w", err) + } + } + ts := pcommon.NewTimestampFromTime(time.Now()) + rms := out.ResourceMetrics() + rm := rms.AppendEmpty() + sms := rm.ScopeMetrics() + sm := sms.AppendEmpty() + ms := sm.Metrics() + var errs error + for _, metricCfg := range s.Query.Metrics { + for i, row := range rows { + if err = rowToMetric(row, metricCfg, ms.AppendEmpty(), s.StartTime, ts, s.ScrapeCfg); err != nil { + err = fmt.Errorf("row %d: %w", i, err) + errs = multierr.Append(errs, err) + } + } + } + if errs != nil { + return out, scrapererror.NewPartialScrapeError(errs, len(multierr.Errors(errs))) + } + return out, nil +} + +func (s *Scraper) Shutdown(_ context.Context) error { + if s.Db != nil { + return s.Db.Close() + } + return nil +} diff --git a/receiver/sqlqueryreceiver/scraper_test.go b/internal/sqlquery/scraper_test.go similarity index 83% rename from receiver/sqlqueryreceiver/scraper_test.go rename to internal/sqlquery/scraper_test.go index fc43e545b7e4..e4567a189459 100644 --- a/receiver/sqlqueryreceiver/scraper_test.go +++ b/internal/sqlquery/scraper_test.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package sqlqueryreceiver +package sqlquery // import "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" import ( "context" @@ -19,8 +19,8 @@ import ( ) func TestScraper_ErrorOnStart(t *testing.T) { - scrpr := scraper{ - dbProviderFunc: func() (*sql.DB, error) { + scrpr := Scraper{ + DbProviderFunc: func() (*sql.DB, error) { return nil, errors.New("oops") }, } @@ -29,25 +29,25 @@ func TestScraper_ErrorOnStart(t *testing.T) { } func TestScraper_ClientErrorOnScrape(t *testing.T) { - client := &fakeDBClient{ - err: errors.New("oops"), + client := &FakeDBClient{ + Err: errors.New("oops"), } - scrpr := scraper{ - client: client, + scrpr := Scraper{ + Client: client, } _, err := scrpr.Scrape(context.Background()) require.Error(t, err) } func TestScraper_RowToMetricErrorOnScrape_Float(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{ {{"myfloat": "blah"}}, }, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.float", ValueColumn: "myfloat", @@ -62,14 +62,14 @@ func TestScraper_RowToMetricErrorOnScrape_Float(t *testing.T) { } func TestScraper_RowToMetricErrorOnScrape_Int(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{ {{"myint": "blah"}}, }, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.int", ValueColumn: "myint", @@ -84,15 +84,15 @@ func TestScraper_RowToMetricErrorOnScrape_Int(t *testing.T) { } func TestScraper_RowToMetricMultiErrorsOnScrape(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{{ {"myint": "foo"}, {"myint": "bar"}, }}, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.col", ValueColumn: "mycol", @@ -107,15 +107,15 @@ func TestScraper_RowToMetricMultiErrorsOnScrape(t *testing.T) { } func TestScraper_SingleRow_MultiMetrics(t *testing.T) { - scrpr := scraper{ - client: &fakeDBClient{ - stringMaps: [][]stringMap{{{ + scrpr := Scraper{ + Client: &FakeDBClient{ + StringMaps: [][]StringMap{{{ "count": "42", "foo_name": "baz", "bar_name": "quux", }}}, }, - query: Query{ + Query: Query{ Metrics: []MetricCfg{ { MetricName: "my.metric.1", @@ -178,8 +178,8 @@ func TestScraper_SingleRow_MultiMetrics(t *testing.T) { } func TestScraper_MultiRow(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{{ { "count": "42", "genre": "action", @@ -190,9 +190,9 @@ func TestScraper_MultiRow(t *testing.T) { }, }}, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{ { MetricName: "movie.genre", @@ -224,15 +224,15 @@ func TestScraper_MultiRow(t *testing.T) { } func TestScraper_MultiResults_CumulativeSum(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{ {{"count": "42"}}, {{"count": "43"}}, }, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "transaction.count", ValueColumn: "count", @@ -247,15 +247,15 @@ func TestScraper_MultiResults_CumulativeSum(t *testing.T) { } func TestScraper_MultiResults_DeltaSum(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{ {{"count": "42"}}, {{"count": "43"}}, }, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "transaction.count", ValueColumn: "count", @@ -269,7 +269,7 @@ func TestScraper_MultiResults_DeltaSum(t *testing.T) { assertTransactionCount(t, scrpr, 43, pmetric.AggregationTemporalityDelta) } -func assertTransactionCount(t *testing.T, scrpr scraper, expected int, agg pmetric.AggregationTemporality) { +func assertTransactionCount(t *testing.T, scrpr Scraper, expected int, agg pmetric.AggregationTemporality) { metrics, err := scrpr.Scrape(context.Background()) require.NoError(t, err) metric := metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(0) @@ -284,14 +284,14 @@ func assertTransactionCount(t *testing.T, scrpr scraper, expected int, agg pmetr } func TestScraper_Float(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{ {{"myfloat": "123.4"}}, }, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.float", ValueColumn: "myfloat", @@ -308,14 +308,14 @@ func TestScraper_Float(t *testing.T) { } func TestScraper_DescriptionAndUnit(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{ {{"mycol": "123"}}, }, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.name", ValueColumn: "mycol", @@ -334,10 +334,10 @@ func TestScraper_DescriptionAndUnit(t *testing.T) { func TestScraper_FakeDB_Warnings(t *testing.T) { db := fakeDB{rowVals: [][]any{{42, nil}}} logger := zap.NewNop() - scrpr := scraper{ - client: newDbClient(db, "", logger, TelemetryConfig{}), - logger: logger, - query: Query{ + scrpr := Scraper{ + Client: NewDbClient(db, "", logger, TelemetryConfig{}), + Logger: logger, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.name", ValueColumn: "col_0", @@ -353,10 +353,10 @@ func TestScraper_FakeDB_Warnings(t *testing.T) { func TestScraper_FakeDB_MultiRows_Warnings(t *testing.T) { db := fakeDB{rowVals: [][]any{{42, nil}, {43, nil}}} logger := zap.NewNop() - scrpr := scraper{ - client: newDbClient(db, "", logger, TelemetryConfig{}), - logger: logger, - query: Query{ + scrpr := Scraper{ + Client: NewDbClient(db, "", logger, TelemetryConfig{}), + Logger: logger, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.col.0", ValueColumn: "col_0", @@ -374,10 +374,10 @@ func TestScraper_FakeDB_MultiRows_Warnings(t *testing.T) { func TestScraper_FakeDB_MultiRows_Error(t *testing.T) { db := fakeDB{rowVals: [][]any{{42, nil}, {43, nil}}} logger := zap.NewNop() - scrpr := scraper{ - client: newDbClient(db, "", logger, TelemetryConfig{}), - logger: logger, - query: Query{ + scrpr := Scraper{ + Client: NewDbClient(db, "", logger, TelemetryConfig{}), + Logger: logger, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.col.0", ValueColumn: "col_0", @@ -395,14 +395,14 @@ func TestScraper_FakeDB_MultiRows_Error(t *testing.T) { _, err := scrpr.Scrape(context.Background()) // We expect an error here not directly because of the NULL values but because // the column was also requested in Query.Metrics[1] but wasn't found. It's just - // a partial scrape error though so it shouldn't cause a scraper shutdown. + // a partial scrape error though so it shouldn't cause a Scraper shutdown. assert.Error(t, err) assert.True(t, scrapererror.IsPartialScrapeError(err)) } func TestScraper_StartAndTSColumn(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{{ { "mycol": "42", "StartTs": "1682417791", @@ -410,9 +410,9 @@ func TestScraper_StartAndTSColumn(t *testing.T) { }, }}, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.name", ValueColumn: "mycol", @@ -431,17 +431,17 @@ func TestScraper_StartAndTSColumn(t *testing.T) { } func TestScraper_StartAndTS_ErrorOnColumnNotFound(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{{ { "mycol": "42", "StartTs": "1682417791", }, }}, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.name", ValueColumn: "mycol", @@ -457,17 +457,17 @@ func TestScraper_StartAndTS_ErrorOnColumnNotFound(t *testing.T) { } func TestScraper_StartAndTS_ErrorOnParse(t *testing.T) { - client := &fakeDBClient{ - stringMaps: [][]stringMap{{ + client := &FakeDBClient{ + StringMaps: [][]StringMap{{ { "mycol": "42", "StartTs": "blah", }, }}, } - scrpr := scraper{ - client: client, - query: Query{ + scrpr := Scraper{ + Client: client, + Query: Query{ Metrics: []MetricCfg{{ MetricName: "my.name", ValueColumn: "mycol", diff --git a/receiver/sqlqueryreceiver/config.go b/receiver/sqlqueryreceiver/config.go index 5b37abf5f58a..d83427f37365 100644 --- a/receiver/sqlqueryreceiver/config.go +++ b/receiver/sqlqueryreceiver/config.go @@ -4,186 +4,29 @@ package sqlqueryreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver" import ( - "errors" - "fmt" "time" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/receiver/scraperhelper" - "go.uber.org/multierr" + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver/internal/metadata" ) type Config struct { - scraperhelper.ScraperControllerSettings `mapstructure:",squash"` - Driver string `mapstructure:"driver"` - DataSource string `mapstructure:"datasource"` - Queries []Query `mapstructure:"queries"` - StorageID *component.ID `mapstructure:"storage"` - Telemetry TelemetryConfig `mapstructure:"telemetry"` + sqlquery.Config `mapstructure:",squash"` } func (c Config) Validate() error { - if c.Driver == "" { - return errors.New("'driver' cannot be empty") - } - if c.DataSource == "" { - return errors.New("'datasource' cannot be empty") - } - if len(c.Queries) == 0 { - return errors.New("'queries' cannot be empty") - } - for _, query := range c.Queries { - if err := query.Validate(); err != nil { - return err - } - } return nil } -type Query struct { - SQL string `mapstructure:"sql"` - Metrics []MetricCfg `mapstructure:"metrics"` - Logs []LogsCfg `mapstructure:"logs"` - TrackingColumn string `mapstructure:"tracking_column"` - TrackingStartValue string `mapstructure:"tracking_start_value"` -} - -func (q Query) Validate() error { - var errs error - if q.SQL == "" { - errs = multierr.Append(errs, errors.New("'query.sql' cannot be empty")) - } - if len(q.Logs) == 0 && len(q.Metrics) == 0 { - errs = multierr.Append(errs, errors.New("at least one of 'query.logs' and 'query.metrics' must not be empty")) - } - for _, logs := range q.Logs { - if err := logs.Validate(); err != nil { - errs = multierr.Append(errs, err) - } - } - for _, metric := range q.Metrics { - if err := metric.Validate(); err != nil { - errs = multierr.Append(errs, err) - } - } - return errs -} - -type LogsCfg struct { - BodyColumn string `mapstructure:"body_column"` -} - -func (config LogsCfg) Validate() error { - var errs error - if config.BodyColumn == "" { - errs = multierr.Append(errs, errors.New("'body_column' must not be empty")) - } - return errs -} - -type MetricCfg struct { - MetricName string `mapstructure:"metric_name"` - ValueColumn string `mapstructure:"value_column"` - AttributeColumns []string `mapstructure:"attribute_columns"` - Monotonic bool `mapstructure:"monotonic"` - ValueType MetricValueType `mapstructure:"value_type"` - DataType MetricType `mapstructure:"data_type"` - Aggregation MetricAggregation `mapstructure:"aggregation"` - Unit string `mapstructure:"unit"` - Description string `mapstructure:"description"` - StaticAttributes map[string]string `mapstructure:"static_attributes"` - StartTsColumn string `mapstructure:"start_ts_column"` - TsColumn string `mapstructure:"ts_column"` -} - -func (c MetricCfg) Validate() error { - var errs error - if c.MetricName == "" { - errs = multierr.Append(errs, errors.New("'metric_name' cannot be empty")) - } - if c.ValueColumn == "" { - errs = multierr.Append(errs, errors.New("'value_column' cannot be empty")) - } - if err := c.ValueType.Validate(); err != nil { - errs = multierr.Append(errs, err) - } - if err := c.DataType.Validate(); err != nil { - errs = multierr.Append(errs, err) - } - if err := c.Aggregation.Validate(); err != nil { - errs = multierr.Append(errs, err) - } - if c.DataType == MetricTypeGauge && c.Aggregation != "" { - errs = multierr.Append(errs, fmt.Errorf("aggregation=%s but data_type=%s does not support aggregation", c.Aggregation, c.DataType)) - } - if errs != nil && c.MetricName != "" { - errs = multierr.Append(fmt.Errorf("invalid metric config with metric_name '%s'", c.MetricName), errs) - } - return errs -} - -type MetricType string - -const ( - MetricTypeUnspecified MetricType = "" - MetricTypeGauge MetricType = "gauge" - MetricTypeSum MetricType = "sum" -) - -func (t MetricType) Validate() error { - switch t { - case MetricTypeUnspecified, MetricTypeGauge, MetricTypeSum: - return nil - } - return fmt.Errorf("metric config has unsupported data_type: '%s'", t) -} - -type MetricValueType string - -const ( - MetricValueTypeUnspecified MetricValueType = "" - MetricValueTypeInt MetricValueType = "int" - MetricValueTypeDouble MetricValueType = "double" -) - -func (t MetricValueType) Validate() error { - switch t { - case MetricValueTypeUnspecified, MetricValueTypeInt, MetricValueTypeDouble: - return nil - } - return fmt.Errorf("metric config has unsupported value_type: '%s'", t) -} - -type MetricAggregation string - -const ( - MetricAggregationUnspecified MetricAggregation = "" - MetricAggregationCumulative MetricAggregation = "cumulative" - MetricAggregationDelta MetricAggregation = "delta" -) - -func (a MetricAggregation) Validate() error { - switch a { - case MetricAggregationUnspecified, MetricAggregationCumulative, MetricAggregationDelta: - return nil - } - return fmt.Errorf("metric config has unsupported aggregation: '%s'", a) -} - func createDefaultConfig() component.Config { cfg := scraperhelper.NewDefaultScraperControllerSettings(metadata.Type) cfg.CollectionInterval = 10 * time.Second return &Config{ - ScraperControllerSettings: cfg, + Config: sqlquery.Config{ + ScraperControllerSettings: cfg, + }, } } - -type TelemetryConfig struct { - Logs TelemetryLogsConfig `mapstructure:"logs"` -} - -type TelemetryLogsConfig struct { - Query bool `mapstructure:"query"` -} diff --git a/receiver/sqlqueryreceiver/config_test.go b/receiver/sqlqueryreceiver/config_test.go index 56893e428f94..d4d4e11b2f7f 100644 --- a/receiver/sqlqueryreceiver/config_test.go +++ b/receiver/sqlqueryreceiver/config_test.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/collector/confmap/confmaptest" "go.opentelemetry.io/collector/receiver/scraperhelper" + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver/internal/metadata" ) @@ -30,25 +31,27 @@ func TestLoadConfig(t *testing.T) { id: component.NewIDWithName(metadata.Type, ""), fname: "config.yaml", expected: &Config{ - ScraperControllerSettings: scraperhelper.ScraperControllerSettings{ - CollectionInterval: 10 * time.Second, - InitialDelay: time.Second, - }, - Driver: "mydriver", - DataSource: "host=localhost port=5432 user=me password=s3cr3t sslmode=disable", - Queries: []Query{ - { - SQL: "select count(*) as count, type from mytable group by type", - Metrics: []MetricCfg{ - { - MetricName: "val.count", - ValueColumn: "count", - AttributeColumns: []string{"type"}, - Monotonic: false, - ValueType: MetricValueTypeInt, - DataType: MetricTypeSum, - Aggregation: MetricAggregationCumulative, - StaticAttributes: map[string]string{"foo": "bar"}, + Config: sqlquery.Config{ + ScraperControllerSettings: scraperhelper.ScraperControllerSettings{ + CollectionInterval: 10 * time.Second, + InitialDelay: time.Second, + }, + Driver: "mydriver", + DataSource: "host=localhost port=5432 user=me password=s3cr3t sslmode=disable", + Queries: []sqlquery.Query{ + { + SQL: "select count(*) as count, type from mytable group by type", + Metrics: []sqlquery.MetricCfg{ + { + MetricName: "val.count", + ValueColumn: "count", + AttributeColumns: []string{"type"}, + Monotonic: false, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeSum, + Aggregation: sqlquery.MetricAggregationCumulative, + StaticAttributes: map[string]string{"foo": "bar"}, + }, }, }, }, @@ -109,20 +112,22 @@ func TestLoadConfig(t *testing.T) { fname: "config-logs.yaml", id: component.NewIDWithName(metadata.Type, ""), expected: &Config{ - ScraperControllerSettings: scraperhelper.ScraperControllerSettings{ - CollectionInterval: 10 * time.Second, - InitialDelay: time.Second, - }, - Driver: "mydriver", - DataSource: "host=localhost port=5432 user=me password=s3cr3t sslmode=disable", - Queries: []Query{ - { - SQL: "select * from test_logs where log_id > ?", - TrackingColumn: "log_id", - TrackingStartValue: "10", - Logs: []LogsCfg{ - { - BodyColumn: "log_body", + Config: sqlquery.Config{ + ScraperControllerSettings: scraperhelper.ScraperControllerSettings{ + CollectionInterval: 10 * time.Second, + InitialDelay: time.Second, + }, + Driver: "mydriver", + DataSource: "host=localhost port=5432 user=me password=s3cr3t sslmode=disable", + Queries: []sqlquery.Query{ + { + SQL: "select * from test_logs where log_id > ?", + TrackingColumn: "log_id", + TrackingStartValue: "10", + Logs: []sqlquery.LogsCfg{ + { + BodyColumn: "log_body", + }, }, }, }, @@ -165,7 +170,7 @@ func TestLoadConfig(t *testing.T) { func TestCreateDefaultConfig(t *testing.T) { cfg := createDefaultConfig().(*Config) - assert.Equal(t, 10*time.Second, cfg.ScraperControllerSettings.CollectionInterval) + assert.Equal(t, 10*time.Second, cfg.Config.ScraperControllerSettings.CollectionInterval) } func TestConfig_Validate_Multierr(t *testing.T) { diff --git a/receiver/sqlqueryreceiver/db_client.go b/receiver/sqlqueryreceiver/db_client.go deleted file mode 100644 index 2afa56f3e51e..000000000000 --- a/receiver/sqlqueryreceiver/db_client.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package sqlqueryreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver" - -import ( - "context" - - // register db drivers - _ "github.com/SAP/go-hdb/driver" - _ "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" - _ "github.com/microsoft/go-mssqldb" - _ "github.com/microsoft/go-mssqldb/integratedauth/krb5" - _ "github.com/sijms/go-ora/v2" - _ "github.com/snowflakedb/gosnowflake" - "go.uber.org/multierr" - "go.uber.org/zap" -) - -type stringMap map[string]string - -type dbClient interface { - queryRows(ctx context.Context, args ...any) ([]stringMap, error) -} - -type dbSQLClient struct { - db db - logger *zap.Logger - telemetryConfig TelemetryConfig - sql string -} - -func newDbClient(db db, sql string, logger *zap.Logger, telemetryConfig TelemetryConfig) dbClient { - return dbSQLClient{ - db: db, - sql: sql, - logger: logger, - telemetryConfig: telemetryConfig, - } -} - -func (cl dbSQLClient) queryRows(ctx context.Context, args ...any) ([]stringMap, error) { - cl.logger.Debug("Running query", cl.prepareQueryFields(cl.sql, args)...) - sqlRows, err := cl.db.QueryContext(ctx, cl.sql, args...) - if err != nil { - return nil, err - } - var out []stringMap - colTypes, err := sqlRows.ColumnTypes() - if err != nil { - return nil, err - } - scanner := newRowScanner(colTypes) - var warnings error - for sqlRows.Next() { - err = scanner.scan(sqlRows) - if err != nil { - return nil, err - } - sm, scanErr := scanner.toStringMap() - if scanErr != nil { - warnings = multierr.Append(warnings, scanErr) - } - out = append(out, sm) - } - return out, warnings -} - -func (cl dbSQLClient) prepareQueryFields(sql string, args []any) []zap.Field { - var logFields []zap.Field - if cl.telemetryConfig.Logs.Query { - logFields = append(logFields, zap.String("query", sql)) - logFields = append(logFields, zap.Any("parameters", args)) - } - return logFields -} diff --git a/receiver/sqlqueryreceiver/factory.go b/receiver/sqlqueryreceiver/factory.go index b72c1c37a2f2..2b31320b98d9 100644 --- a/receiver/sqlqueryreceiver/factory.go +++ b/receiver/sqlqueryreceiver/factory.go @@ -8,6 +8,7 @@ import ( "go.opentelemetry.io/collector/receiver" + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver/internal/metadata" ) @@ -15,7 +16,7 @@ func NewFactory() receiver.Factory { return receiver.NewFactory( metadata.Type, createDefaultConfig, - receiver.WithLogs(createLogsReceiverFunc(sql.Open, newDbClient), metadata.LogsStability), - receiver.WithMetrics(createMetricsReceiverFunc(sql.Open, newDbClient), metadata.MetricsStability), + receiver.WithLogs(createLogsReceiverFunc(sql.Open, sqlquery.NewDbClient), metadata.LogsStability), + receiver.WithMetrics(createMetricsReceiverFunc(sql.Open, sqlquery.NewDbClient), metadata.MetricsStability), ) } diff --git a/receiver/sqlqueryreceiver/go.mod b/receiver/sqlqueryreceiver/go.mod index 74e5fcb13a68..77d1d78e48ec 100644 --- a/receiver/sqlqueryreceiver/go.mod +++ b/receiver/sqlqueryreceiver/go.mod @@ -3,17 +3,12 @@ module github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlque go 1.20 require ( - github.com/SAP/go-hdb v1.7.11 github.com/docker/go-connections v0.5.0 - github.com/go-sql-driver/mysql v1.7.1 - github.com/lib/pq v1.10.9 - github.com/microsoft/go-mssqldb v1.6.0 github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.93.0 github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.93.0 + github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery v0.93.0 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.93.0 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.93.0 - github.com/sijms/go-ora/v2 v2.8.6 - github.com/snowflakedb/gosnowflake v1.7.2 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.27.0 go.opentelemetry.io/collector/component v0.93.1-0.20240130182548-89388addcc7f @@ -39,6 +34,7 @@ require ( github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/SAP/go-hdb v1.7.11 // indirect github.com/apache/arrow/go/v14 v14.0.2 // indirect github.com/aws/aws-sdk-go-v2 v1.22.2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect @@ -71,6 +67,7 @@ require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -97,8 +94,10 @@ require ( github.com/knadh/koanf/providers/confmap v0.1.0 // indirect github.com/knadh/koanf/v2 v2.0.1 // indirect github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/microsoft/go-mssqldb v1.6.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect @@ -125,7 +124,9 @@ require ( github.com/prometheus/procfs v0.12.0 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sijms/go-ora/v2 v2.8.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/snowflakedb/gosnowflake v1.7.2 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/valyala/fastjson v1.6.4 // indirect @@ -178,3 +179,5 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza => replace github.com/docker/docker v24.0.4+incompatible => github.com/docker/docker v24.0.5-0.20230719162248-f022632503d1+incompatible replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden => ../../pkg/golden + +replace github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery => ../../internal/sqlquery diff --git a/receiver/sqlqueryreceiver/integration_test.go b/receiver/sqlqueryreceiver/integration_test.go index fe154e3a299d..f8ba19dc4737 100644 --- a/receiver/sqlqueryreceiver/integration_test.go +++ b/receiver/sqlqueryreceiver/integration_test.go @@ -29,6 +29,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/storagetest" "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/scraperinttest" + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest" ) @@ -49,10 +50,10 @@ func TestPostgresIntegrationLogsTrackingWithoutStorage(t *testing.T) { // Start the SQL Query receiver. receiver, config, consumer := createTestLogsReceiverForPostgres(t, externalPort) config.CollectionInterval = time.Second - config.Queries = []Query{ + config.Queries = []sqlquery.Query{ { SQL: "select * from simple_logs where id > $1", - Logs: []LogsCfg{ + Logs: []sqlquery.LogsCfg{ { BodyColumn: "body", }, @@ -85,10 +86,10 @@ func TestPostgresIntegrationLogsTrackingWithoutStorage(t *testing.T) { // Start new SQL Query receiver with the same configuration. receiver, config, consumer = createTestLogsReceiverForPostgres(t, externalPort) config.CollectionInterval = time.Second - config.Queries = []Query{ + config.Queries = []sqlquery.Query{ { SQL: "select * from simple_logs where id > $1", - Logs: []LogsCfg{ + Logs: []sqlquery.LogsCfg{ { BodyColumn: "body", }, @@ -136,10 +137,10 @@ func TestPostgresIntegrationLogsTrackingWithStorage(t *testing.T) { receiver, config, consumer := createTestLogsReceiverForPostgres(t, externalPort) config.CollectionInterval = time.Second config.StorageID = &storageExtension.ID - config.Queries = []Query{ + config.Queries = []sqlquery.Query{ { SQL: "select * from simple_logs where id > $1", - Logs: []LogsCfg{ + Logs: []sqlquery.LogsCfg{ { BodyColumn: "body", }, @@ -178,10 +179,10 @@ func TestPostgresIntegrationLogsTrackingWithStorage(t *testing.T) { receiver, config, consumer = createTestLogsReceiverForPostgres(t, externalPort) config.CollectionInterval = time.Second config.StorageID = &storageExtension.ID - config.Queries = []Query{ + config.Queries = []sqlquery.Query{ { SQL: "select * from simple_logs where id > $1", - Logs: []LogsCfg{ + Logs: []sqlquery.LogsCfg{ { BodyColumn: "body", }, @@ -211,10 +212,10 @@ func TestPostgresIntegrationLogsTrackingWithStorage(t *testing.T) { receiver, config, consumer = createTestLogsReceiverForPostgres(t, externalPort) config.CollectionInterval = time.Second config.StorageID = &storageExtension.ID - config.Queries = []Query{ + config.Queries = []sqlquery.Query{ { SQL: "select * from simple_logs where id > $1", - Logs: []LogsCfg{ + Logs: []sqlquery.LogsCfg{ { BodyColumn: "body", }, @@ -354,77 +355,77 @@ func TestPostgresqlIntegrationMetrics(t *testing.T) { rCfg.Driver = "postgres" rCfg.DataSource = fmt.Sprintf("host=%s port=%s user=otel password=otel sslmode=disable", ci.Host(t), ci.MappedPort(t, postgresqlPort)) - rCfg.Queries = []Query{ + rCfg.Queries = []sqlquery.Query{ { SQL: "select genre, count(*), avg(imdb_rating) from movie group by genre", - Metrics: []MetricCfg{ + Metrics: []sqlquery.MetricCfg{ { MetricName: "genre.count", ValueColumn: "count", AttributeColumns: []string{"genre"}, - ValueType: MetricValueTypeInt, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "genre.imdb", ValueColumn: "avg", AttributeColumns: []string{"genre"}, - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, }, }, { SQL: "select 1::smallint as a, 2::integer as b, 3::bigint as c, 4.1::decimal as d," + " 4.2::numeric as e, 4.3::real as f, 4.4::double precision as g, null as h", - Metrics: []MetricCfg{ + Metrics: []sqlquery.MetricCfg{ { MetricName: "a", ValueColumn: "a", - ValueType: MetricValueTypeInt, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "b", ValueColumn: "b", - ValueType: MetricValueTypeInt, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "c", ValueColumn: "c", - ValueType: MetricValueTypeInt, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "d", ValueColumn: "d", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "e", ValueColumn: "e", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "f", ValueColumn: "f", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "g", ValueColumn: "g", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "h", ValueColumn: "h", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, }, }, @@ -467,23 +468,23 @@ func TestOracleDBIntegrationMetrics(t *testing.T) { rCfg.Driver = "oracle" rCfg.DataSource = fmt.Sprintf("oracle://otel:p@ssw%%25rd@%s:%s/XE", ci.Host(t), ci.MappedPort(t, oraclePort)) - rCfg.Queries = []Query{ + rCfg.Queries = []sqlquery.Query{ { SQL: "select genre, count(*) as count, avg(imdb_rating) as avg from sys.movie group by genre", - Metrics: []MetricCfg{ + Metrics: []sqlquery.MetricCfg{ { MetricName: "genre.count", ValueColumn: "COUNT", AttributeColumns: []string{"GENRE"}, - ValueType: MetricValueTypeInt, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "genre.imdb", ValueColumn: "AVG", AttributeColumns: []string{"GENRE"}, - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, }, }, @@ -524,23 +525,23 @@ func TestMysqlIntegrationMetrics(t *testing.T) { rCfg.Driver = "mysql" rCfg.DataSource = fmt.Sprintf("otel:otel@tcp(%s:%s)/otel", ci.Host(t), ci.MappedPort(t, mysqlPort)) - rCfg.Queries = []Query{ + rCfg.Queries = []sqlquery.Query{ { SQL: "select genre, count(*), avg(imdb_rating) from movie group by genre", - Metrics: []MetricCfg{ + Metrics: []sqlquery.MetricCfg{ { MetricName: "genre.count", ValueColumn: "count(*)", AttributeColumns: []string{"genre"}, - ValueType: MetricValueTypeInt, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "genre.imdb", ValueColumn: "avg(imdb_rating)", AttributeColumns: []string{"genre"}, - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, }, }, @@ -553,42 +554,42 @@ func TestMysqlIntegrationMetrics(t *testing.T) { "cast(3.3 as float) as e, " + "cast(3.4 as double) as f, " + "null as g", - Metrics: []MetricCfg{ + Metrics: []sqlquery.MetricCfg{ { MetricName: "a", ValueColumn: "a", - ValueType: MetricValueTypeInt, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "b", ValueColumn: "b", - ValueType: MetricValueTypeInt, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeInt, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "c", ValueColumn: "c", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "d", ValueColumn: "d", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "e", ValueColumn: "e", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, { MetricName: "f", ValueColumn: "f", - ValueType: MetricValueTypeDouble, - DataType: MetricTypeGauge, + ValueType: sqlquery.MetricValueTypeDouble, + DataType: sqlquery.MetricTypeGauge, }, }, }, diff --git a/receiver/sqlqueryreceiver/logs_receiver.go b/receiver/sqlqueryreceiver/logs_receiver.go index fb24433b5177..7372f8dcd47f 100644 --- a/receiver/sqlqueryreceiver/logs_receiver.go +++ b/receiver/sqlqueryreceiver/logs_receiver.go @@ -19,6 +19,7 @@ import ( "go.uber.org/multierr" "go.uber.org/zap" + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/adapter" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver/internal/metadata" ) @@ -26,8 +27,8 @@ import ( type logsReceiver struct { config *Config settings receiver.CreateSettings - createConnection dbProviderFunc - createClient clientProviderFunc + createConnection sqlquery.DbProviderFunc + createClient sqlquery.ClientProviderFunc queryReceivers []*logsQueryReceiver nextConsumer consumer.Logs @@ -43,8 +44,8 @@ type logsReceiver struct { func newLogsReceiver( config *Config, settings receiver.CreateSettings, - sqlOpenerFunc sqlOpenerFunc, - createClient clientProviderFunc, + sqlOpenerFunc sqlquery.SQLOpenerFunc, + createClient sqlquery.ClientProviderFunc, nextConsumer consumer.Logs, ) (*logsReceiver, error) { @@ -199,14 +200,14 @@ func (receiver *logsReceiver) stopCollecting() { type logsQueryReceiver struct { id string - query Query - createDb dbProviderFunc - createClient clientProviderFunc + query sqlquery.Query + createDb sqlquery.DbProviderFunc + createClient sqlquery.ClientProviderFunc logger *zap.Logger - telemetry TelemetryConfig + telemetry sqlquery.TelemetryConfig db *sql.DB - client dbClient + client sqlquery.DbClient trackingValue string // TODO: Extract persistence into its own component storageClient storage.Client @@ -215,11 +216,11 @@ type logsQueryReceiver struct { func newLogsQueryReceiver( id string, - query Query, - dbProviderFunc dbProviderFunc, - clientProviderFunc clientProviderFunc, + query sqlquery.Query, + dbProviderFunc sqlquery.DbProviderFunc, + clientProviderFunc sqlquery.ClientProviderFunc, logger *zap.Logger, - telemetry TelemetryConfig, + telemetry sqlquery.TelemetryConfig, storageClient storage.Client, ) *logsQueryReceiver { queryReceiver := &logsQueryReceiver{ @@ -246,7 +247,7 @@ func (queryReceiver *logsQueryReceiver) start(ctx context.Context) error { if err != nil { return fmt.Errorf("failed to open db connection: %w", err) } - queryReceiver.client = queryReceiver.createClient(dbWrapper{queryReceiver.db}, queryReceiver.query.SQL, queryReceiver.logger, queryReceiver.telemetry) + queryReceiver.client = queryReceiver.createClient(sqlquery.DbWrapper{Db: queryReceiver.db}, queryReceiver.query.SQL, queryReceiver.logger, queryReceiver.telemetry) queryReceiver.trackingValue = queryReceiver.retrieveTrackingValue(ctx) @@ -273,13 +274,13 @@ func (queryReceiver *logsQueryReceiver) retrieveTrackingValue(ctx context.Contex func (queryReceiver *logsQueryReceiver) collect(ctx context.Context) (plog.Logs, error) { logs := plog.NewLogs() - var rows []stringMap + var rows []sqlquery.StringMap var err error observedAt := pcommon.NewTimestampFromTime(time.Now()) if queryReceiver.query.TrackingColumn != "" { - rows, err = queryReceiver.client.queryRows(ctx, queryReceiver.trackingValue) + rows, err = queryReceiver.client.QueryRows(ctx, queryReceiver.trackingValue) } else { - rows, err = queryReceiver.client.queryRows(ctx) + rows, err = queryReceiver.client.QueryRows(ctx) } if err != nil { return logs, fmt.Errorf("error getting rows: %w", err) @@ -300,7 +301,7 @@ func (queryReceiver *logsQueryReceiver) collect(ctx context.Context) (plog.Logs, return logs, nil } -func (queryReceiver *logsQueryReceiver) storeTrackingValue(ctx context.Context, row stringMap) error { +func (queryReceiver *logsQueryReceiver) storeTrackingValue(ctx context.Context, row sqlquery.StringMap) error { if queryReceiver.query.TrackingColumn == "" { return nil } @@ -314,7 +315,7 @@ func (queryReceiver *logsQueryReceiver) storeTrackingValue(ctx context.Context, return nil } -func rowToLog(row stringMap, config LogsCfg, logRecord plog.LogRecord) { +func rowToLog(row sqlquery.StringMap, config sqlquery.LogsCfg, logRecord plog.LogRecord) { logRecord.Body().SetStr(row[config.BodyColumn]) } diff --git a/receiver/sqlqueryreceiver/logs_receiver_test.go b/receiver/sqlqueryreceiver/logs_receiver_test.go index b78b698bc898..34877c23ce23 100644 --- a/receiver/sqlqueryreceiver/logs_receiver_test.go +++ b/receiver/sqlqueryreceiver/logs_receiver_test.go @@ -10,20 +10,22 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/pcommon" + + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" ) func TestLogsQueryReceiver_Collect(t *testing.T) { now := time.Now() - fakeClient := &fakeDBClient{ - stringMaps: [][]stringMap{ + fakeClient := &sqlquery.FakeDBClient{ + StringMaps: [][]sqlquery.StringMap{ {{"col1": "42"}, {"col1": "63"}}, }, } queryReceiver := logsQueryReceiver{ client: fakeClient, - query: Query{ - Logs: []LogsCfg{ + query: sqlquery.Query{ + Logs: []sqlquery.LogsCfg{ { BodyColumn: "col1", }, diff --git a/receiver/sqlqueryreceiver/receiver.go b/receiver/sqlqueryreceiver/receiver.go index 3228d51fcd9e..f9b54613e6e5 100644 --- a/receiver/sqlqueryreceiver/receiver.go +++ b/receiver/sqlqueryreceiver/receiver.go @@ -12,16 +12,11 @@ import ( "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/scraperhelper" - "go.uber.org/zap" -) - -type sqlOpenerFunc func(driverName, dataSourceName string) (*sql.DB, error) - -type dbProviderFunc func() (*sql.DB, error) -type clientProviderFunc func(db, string, *zap.Logger, TelemetryConfig) dbClient + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" +) -func createLogsReceiverFunc(sqlOpenerFunc sqlOpenerFunc, clientProviderFunc clientProviderFunc) receiver.CreateLogsFunc { +func createLogsReceiverFunc(sqlOpenerFunc sqlquery.SQLOpenerFunc, clientProviderFunc sqlquery.ClientProviderFunc) receiver.CreateLogsFunc { return func( ctx context.Context, settings receiver.CreateSettings, @@ -33,7 +28,7 @@ func createLogsReceiverFunc(sqlOpenerFunc sqlOpenerFunc, clientProviderFunc clie } } -func createMetricsReceiverFunc(sqlOpenerFunc sqlOpenerFunc, clientProviderFunc clientProviderFunc) receiver.CreateMetricsFunc { +func createMetricsReceiverFunc(sqlOpenerFunc sqlquery.SQLOpenerFunc, clientProviderFunc sqlquery.ClientProviderFunc) receiver.CreateMetricsFunc { return func( ctx context.Context, settings receiver.CreateSettings, @@ -47,17 +42,11 @@ func createMetricsReceiverFunc(sqlOpenerFunc sqlOpenerFunc, clientProviderFunc c continue } id := component.NewIDWithName("sqlqueryreceiver", fmt.Sprintf("query-%d: %s", i, query.SQL)) - mp := &scraper{ - id: id, - query: query, - scrapeCfg: sqlCfg.ScraperControllerSettings, - logger: settings.TelemetrySettings.Logger, - telemetry: sqlCfg.Telemetry, - dbProviderFunc: func() (*sql.DB, error) { - return sqlOpenerFunc(sqlCfg.Driver, sqlCfg.DataSource) - }, - clientProviderFunc: clientProviderFunc, + dbProviderFunc := func() (*sql.DB, error) { + return sqlOpenerFunc(sqlCfg.Driver, sqlCfg.DataSource) } + mp := sqlquery.NewScraper(id, query, sqlCfg.ScraperControllerSettings, settings.TelemetrySettings.Logger, sqlCfg.Config.Telemetry, dbProviderFunc, clientProviderFunc) + opt := scraperhelper.AddScraper(mp) opts = append(opts, opt) } diff --git a/receiver/sqlqueryreceiver/receiver_test.go b/receiver/sqlqueryreceiver/receiver_test.go index 7d222bc8613b..ff5cd49f9d53 100644 --- a/receiver/sqlqueryreceiver/receiver_test.go +++ b/receiver/sqlqueryreceiver/receiver_test.go @@ -15,6 +15,8 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" "go.opentelemetry.io/collector/receiver/scraperhelper" "go.uber.org/zap" + + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery" ) func TestCreateLogsReceiver(t *testing.T) { @@ -24,17 +26,19 @@ func TestCreateLogsReceiver(t *testing.T) { ctx, receivertest.NewNopCreateSettings(), &Config{ - ScraperControllerSettings: scraperhelper.ScraperControllerSettings{ - CollectionInterval: 10 * time.Second, - }, - Driver: "mydriver", - DataSource: "my-datasource", - Queries: []Query{{ - SQL: "select * from foo", - Logs: []LogsCfg{ - {}, + Config: sqlquery.Config{ + ScraperControllerSettings: scraperhelper.ScraperControllerSettings{ + CollectionInterval: 10 * time.Second, }, - }}, + Driver: "mydriver", + DataSource: "my-datasource", + Queries: []sqlquery.Query{{ + SQL: "select * from foo", + Logs: []sqlquery.LogsCfg{ + {}, + }, + }}, + }, }, consumertest.NewNop(), ) @@ -50,19 +54,21 @@ func TestCreateMetricsReceiver(t *testing.T) { ctx, receivertest.NewNopCreateSettings(), &Config{ - ScraperControllerSettings: scraperhelper.ScraperControllerSettings{ - CollectionInterval: 10 * time.Second, - InitialDelay: time.Second, - }, - Driver: "mydriver", - DataSource: "my-datasource", - Queries: []Query{{ - SQL: "select * from foo", - Metrics: []MetricCfg{{ - MetricName: "my-metric", - ValueColumn: "my-column", + Config: sqlquery.Config{ + ScraperControllerSettings: scraperhelper.ScraperControllerSettings{ + CollectionInterval: 10 * time.Second, + InitialDelay: time.Second, + }, + Driver: "mydriver", + DataSource: "my-datasource", + Queries: []sqlquery.Query{{ + SQL: "select * from foo", + Metrics: []sqlquery.MetricCfg{{ + MetricName: "my-metric", + ValueColumn: "my-column", + }}, }}, - }}, + }, }, consumertest.NewNop(), ) @@ -75,6 +81,6 @@ func fakeDBConnect(string, string) (*sql.DB, error) { return nil, nil } -func mkFakeClient(db, string, *zap.Logger, TelemetryConfig) dbClient { - return &fakeDBClient{stringMaps: [][]stringMap{{{"foo": "111"}}}} +func mkFakeClient(sqlquery.Db, string, *zap.Logger, sqlquery.TelemetryConfig) sqlquery.DbClient { + return &sqlquery.FakeDBClient{StringMaps: [][]sqlquery.StringMap{{{"foo": "111"}}}} } diff --git a/receiver/sqlqueryreceiver/scraper.go b/receiver/sqlqueryreceiver/scraper.go deleted file mode 100644 index babd119be87f..000000000000 --- a/receiver/sqlqueryreceiver/scraper.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package sqlqueryreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sqlqueryreceiver" - -import ( - "context" - "database/sql" - "errors" - "fmt" - "time" - - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/pdata/pcommon" - "go.opentelemetry.io/collector/pdata/pmetric" - "go.opentelemetry.io/collector/receiver/scrapererror" - "go.opentelemetry.io/collector/receiver/scraperhelper" - "go.uber.org/multierr" - "go.uber.org/zap" -) - -type scraper struct { - id component.ID - query Query - scrapeCfg scraperhelper.ScraperControllerSettings - startTime pcommon.Timestamp - clientProviderFunc clientProviderFunc - dbProviderFunc dbProviderFunc - logger *zap.Logger - telemetry TelemetryConfig - client dbClient - db *sql.DB -} - -var _ scraperhelper.Scraper = (*scraper)(nil) - -func (s *scraper) ID() component.ID { - return s.id -} - -func (s *scraper) Start(context.Context, component.Host) error { - var err error - s.db, err = s.dbProviderFunc() - if err != nil { - return fmt.Errorf("failed to open db connection: %w", err) - } - s.client = s.clientProviderFunc(dbWrapper{s.db}, s.query.SQL, s.logger, s.telemetry) - s.startTime = pcommon.NewTimestampFromTime(time.Now()) - - return nil -} - -func (s *scraper) Scrape(ctx context.Context) (pmetric.Metrics, error) { - out := pmetric.NewMetrics() - rows, err := s.client.queryRows(ctx) - if err != nil { - if errors.Is(err, errNullValueWarning) { - s.logger.Warn("problems encountered getting metric rows", zap.Error(err)) - } else { - return out, fmt.Errorf("scraper: %w", err) - } - } - ts := pcommon.NewTimestampFromTime(time.Now()) - rms := out.ResourceMetrics() - rm := rms.AppendEmpty() - sms := rm.ScopeMetrics() - sm := sms.AppendEmpty() - ms := sm.Metrics() - var errs error - for _, metricCfg := range s.query.Metrics { - for i, row := range rows { - if err = rowToMetric(row, metricCfg, ms.AppendEmpty(), s.startTime, ts, s.scrapeCfg); err != nil { - err = fmt.Errorf("row %d: %w", i, err) - errs = multierr.Append(errs, err) - } - } - } - if errs != nil { - return out, scrapererror.NewPartialScrapeError(errs, len(multierr.Errors(errs))) - } - return out, nil -} - -func (s *scraper) Shutdown(_ context.Context) error { - if s.db != nil { - return s.db.Close() - } - return nil -} diff --git a/versions.yaml b/versions.yaml index 461476187f9a..71d5e1a15d2c 100644 --- a/versions.yaml +++ b/versions.yaml @@ -119,6 +119,7 @@ module-sets: - github.com/open-telemetry/opentelemetry-collector-contrib/internal/metadataproviders - github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent - github.com/open-telemetry/opentelemetry-collector-contrib/internal/splunk + - github.com/open-telemetry/opentelemetry-collector-contrib/internal/sqlquery - github.com/open-telemetry/opentelemetry-collector-contrib/internal/datadog - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchperresourceattr - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal