diff --git a/.chloggen/drosiek-mysql-perf-metrics.yaml b/.chloggen/drosiek-mysql-perf-metrics.yaml new file mode 100755 index 000000000000..1a1acb62dbcd --- /dev/null +++ b/.chloggen/drosiek-mysql-perf-metrics.yaml @@ -0,0 +1,16 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: receiver/mysql + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: add metrics based on events_statements_summary_by_digest table + +# One or more tracking issues related to the change +issues: [14138] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: diff --git a/receiver/mysqlreceiver/README.md b/receiver/mysqlreceiver/README.md index 8cba9ae6a6c6..4c91e3ca7caa 100644 --- a/receiver/mysqlreceiver/README.md +++ b/receiver/mysqlreceiver/README.md @@ -27,6 +27,10 @@ The following settings are optional: - `collection_interval` (default = `10s`): This receiver collects metrics on an interval. This value must be a string readable by Golang's [time.ParseDuration](https://pkg.go.dev/time#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. - `transport`: (default = `tcp`): Defines the network to use for connecting to the server. +- `statement_events`: Additional configuration for query to build `mysql.statement_events.count` and `mysql.statement_events.wait.time` metrics: + - `digest_text_limit` - maximum length of `digest_text`. Longer text will be truncated (default=`120`) + - `time_limit` - maximum time from since the statements have been observed last time (default=`24h`) + - `limit` - limit of records, which is maximum number of generated metrics (default=`250`) ### Example Configuration @@ -38,6 +42,10 @@ receivers: password: $MYSQL_PASSWORD database: otel collection_interval: 10s + perf_events_statements: + digest_text_limit: 120 + time_limit: 24h + limit: 250 ``` The full list of settings exposed for this receiver are documented [here](./config.go) with detailed sample configurations [here](./testdata/config.yaml). diff --git a/receiver/mysqlreceiver/client.go b/receiver/mysqlreceiver/client.go index fd3b47d2deb3..9b65b79983cd 100644 --- a/receiver/mysqlreceiver/client.go +++ b/receiver/mysqlreceiver/client.go @@ -17,6 +17,7 @@ package mysqlreceiver // import "github.com/open-telemetry/opentelemetry-collect import ( "database/sql" "fmt" + "time" // registers the mysql driver "github.com/go-sql-driver/mysql" @@ -28,12 +29,16 @@ type client interface { getInnodbStats() (map[string]string, error) getTableIoWaitsStats() ([]TableIoWaitsStats, error) getIndexIoWaitsStats() ([]IndexIoWaitsStats, error) + getStatementEventsStats() ([]StatementEventStats, error) Close() error } type mySQLClient struct { - connStr string - client *sql.DB + connStr string + client *sql.DB + statementEventsDigestTextLimit int + statementEventsLimit int + statementEventsTimeLimit time.Duration } type IoWaitsStats struct { @@ -58,6 +63,23 @@ type IndexIoWaitsStats struct { index string } +type StatementEventStats struct { + schema string + digest string + digestText string + sumTimerWait int64 + countErrors int64 + countWarnings int64 + countRowsAffected int64 + countRowsSent int64 + countRowsExamined int64 + countCreatedTmpDiskTables int64 + countCreatedTmpTables int64 + countSortMergePasses int64 + countSortRows int64 + countNoIndexUsed int64 +} + var _ client = (*mySQLClient)(nil) func newMySQLClient(conf *Config) client { @@ -72,7 +94,10 @@ func newMySQLClient(conf *Config) client { connStr := driverConf.FormatDSN() return &mySQLClient{ - connStr: connStr, + connStr: connStr, + statementEventsDigestTextLimit: conf.StatementEvents.DigestTextLimit, + statementEventsLimit: conf.StatementEvents.Limit, + statementEventsTimeLimit: conf.StatementEvents.TimeLimit, } } @@ -152,6 +177,43 @@ func (c *mySQLClient) getIndexIoWaitsStats() ([]IndexIoWaitsStats, error) { return stats, nil } +func (c *mySQLClient) getStatementEventsStats() ([]StatementEventStats, error) { + query := fmt.Sprintf("SELECT ifnull(SCHEMA_NAME, 'NONE') as SCHEMA_NAME, DIGEST,"+ + "LEFT(DIGEST_TEXT, %d) as DIGEST_TEXT, SUM_TIMER_WAIT, SUM_ERRORS,"+ + "SUM_WARNINGS, SUM_ROWS_AFFECTED, SUM_ROWS_SENT, SUM_ROWS_EXAMINED,"+ + "SUM_CREATED_TMP_DISK_TABLES, SUM_CREATED_TMP_TABLES, SUM_SORT_MERGE_PASSES,"+ + "SUM_SORT_ROWS, SUM_NO_INDEX_USED "+ + "FROM performance_schema.events_statements_summary_by_digest "+ + "WHERE SCHEMA_NAME NOT IN ('mysql', 'performance_schema', 'information_schema') "+ + "AND last_seen > DATE_SUB(NOW(), INTERVAL %d SECOND) "+ + "ORDER BY SUM_TIMER_WAIT DESC "+ + "LIMIT %d", + c.statementEventsDigestTextLimit, + int64(c.statementEventsTimeLimit.Seconds()), + c.statementEventsLimit) + + rows, err := c.client.Query(query) + if err != nil { + return nil, err + } + defer rows.Close() + + var stats []StatementEventStats + for rows.Next() { + var s StatementEventStats + err := rows.Scan(&s.schema, &s.digest, &s.digestText, + &s.sumTimerWait, &s.countErrors, &s.countWarnings, + &s.countRowsAffected, &s.countRowsSent, &s.countRowsExamined, &s.countCreatedTmpDiskTables, + &s.countCreatedTmpTables, &s.countSortMergePasses, &s.countSortRows, &s.countNoIndexUsed) + if err != nil { + return nil, err + } + stats = append(stats, s) + } + + return stats, nil +} + func Query(c mySQLClient, query string) (map[string]string, error) { rows, err := c.client.Query(query) if err != nil { diff --git a/receiver/mysqlreceiver/config.go b/receiver/mysqlreceiver/config.go index 650f10f802dc..e3d8ed02a6a4 100644 --- a/receiver/mysqlreceiver/config.go +++ b/receiver/mysqlreceiver/config.go @@ -15,12 +15,20 @@ package mysqlreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysqlreceiver" import ( + "time" + "go.opentelemetry.io/collector/config/confignet" "go.opentelemetry.io/collector/receiver/scraperhelper" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysqlreceiver/internal/metadata" ) +const ( + defaultStatementEventsDigestTextLimit = 120 + defaultStatementEventsLimit = 250 + defaultStatementEventsTimeLimit = 24 * time.Hour +) + type Config struct { scraperhelper.ScraperControllerSettings `mapstructure:",squash"` Username string `mapstructure:"username,omitempty"` @@ -29,4 +37,11 @@ type Config struct { AllowNativePasswords bool `mapstructure:"allow_native_passwords,omitempty"` confignet.NetAddr `mapstructure:",squash"` Metrics metadata.MetricsSettings `mapstructure:"metrics"` + StatementEvents StatementEventsConfig `mapstructure:"statement_events"` +} + +type StatementEventsConfig struct { + DigestTextLimit int `mapstructure:"digest_text_limit"` + Limit int `mapstructure:"limit"` + TimeLimit time.Duration `mapstructure:"time_limit"` } diff --git a/receiver/mysqlreceiver/documentation.md b/receiver/mysqlreceiver/documentation.md index 6d31029765ef..cae126923559 100644 --- a/receiver/mysqlreceiver/documentation.md +++ b/receiver/mysqlreceiver/documentation.md @@ -29,6 +29,8 @@ These are the metrics available for this scraper. | **mysql.row_locks** | The number of InnoDB row locks. | 1 | Sum(Int) | | | **mysql.row_operations** | The number of InnoDB row operations. | 1 | Sum(Int) | | | **mysql.sorts** | The number of MySQL sorts. | 1 | Sum(Int) | | +| mysql.statement_event.count | Summary of current and recent statement events. | 1 | Sum(Int) | | +| mysql.statement_event.wait.time | The total wait time of the summarized timed events. | ns | Sum(Int) | | | **mysql.table.io.wait.count** | The total count of I/O wait events for a table. | 1 | Sum(Int) | | | **mysql.table.io.wait.time** | The total time of I/O wait events for a table. | ns | Sum(Int) | | | **mysql.threads** | The state of MySQL threads. | 1 | Sum(Int) | | @@ -57,7 +59,10 @@ metrics: | buffer_pool_operations (operation) | The buffer pool operations types. | read_ahead_rnd, read_ahead, read_ahead_evicted, read_requests, reads, wait_free, write_requests | | buffer_pool_pages (kind) | The buffer pool pages types. | data, free, misc | | command (command) | The command types. | execute, close, fetch, prepare, reset, send_long_data | +| digest (digest) | Digest. | | +| digest_text (digest_text) | Text before digestion. | | | double_writes (kind) | The doublewrite types. | pages_written, writes | +| event_state (kind) | Possible event states. | errors, warnings, rows_affected, rows_sent, rows_examined, created_tmp_disk_tables, created_tmp_tables, sort_merge_passes, sort_rows, no_index_used | | handler (kind) | The handler types. | commit, delete, discover, external_lock, mrr_init, prepare, read_first, read_key, read_last, read_next, read_prev, read_rnd, read_rnd_next, rollback, savepoint, savepoint_rollback, update, write | | index_name (index) | The name of the index. | | | io_waits_operations (operation) | The io_waits operation type. | delete, fetch, insert, update | diff --git a/receiver/mysqlreceiver/factory.go b/receiver/mysqlreceiver/factory.go index d9fc054e8d67..a5ac04bbc2f5 100644 --- a/receiver/mysqlreceiver/factory.go +++ b/receiver/mysqlreceiver/factory.go @@ -52,6 +52,11 @@ func createDefaultConfig() config.Receiver { Transport: "tcp", }, Metrics: metadata.DefaultMetricsSettings(), + StatementEvents: StatementEventsConfig{ + DigestTextLimit: defaultStatementEventsDigestTextLimit, + Limit: defaultStatementEventsLimit, + TimeLimit: defaultStatementEventsTimeLimit, + }, } } diff --git a/receiver/mysqlreceiver/internal/metadata/generated_metrics.go b/receiver/mysqlreceiver/internal/metadata/generated_metrics.go index 16760266a6ac..021f24e3414a 100644 --- a/receiver/mysqlreceiver/internal/metadata/generated_metrics.go +++ b/receiver/mysqlreceiver/internal/metadata/generated_metrics.go @@ -19,31 +19,33 @@ type MetricSettings struct { // MetricsSettings provides settings for mysqlreceiver metrics. type MetricsSettings struct { - MysqlBufferPoolDataPages MetricSettings `mapstructure:"mysql.buffer_pool.data_pages"` - MysqlBufferPoolLimit MetricSettings `mapstructure:"mysql.buffer_pool.limit"` - MysqlBufferPoolOperations MetricSettings `mapstructure:"mysql.buffer_pool.operations"` - MysqlBufferPoolPageFlushes MetricSettings `mapstructure:"mysql.buffer_pool.page_flushes"` - MysqlBufferPoolPages MetricSettings `mapstructure:"mysql.buffer_pool.pages"` - MysqlBufferPoolUsage MetricSettings `mapstructure:"mysql.buffer_pool.usage"` - MysqlCommands MetricSettings `mapstructure:"mysql.commands"` - MysqlDoubleWrites MetricSettings `mapstructure:"mysql.double_writes"` - MysqlHandlers MetricSettings `mapstructure:"mysql.handlers"` - MysqlIndexIoWaitCount MetricSettings `mapstructure:"mysql.index.io.wait.count"` - MysqlIndexIoWaitTime MetricSettings `mapstructure:"mysql.index.io.wait.time"` - MysqlLockedConnects MetricSettings `mapstructure:"mysql.locked_connects"` - MysqlLocks MetricSettings `mapstructure:"mysql.locks"` - MysqlLogOperations MetricSettings `mapstructure:"mysql.log_operations"` - MysqlMysqlxWorkerThreads MetricSettings `mapstructure:"mysql.mysqlx_worker_threads"` - MysqlOpenedResources MetricSettings `mapstructure:"mysql.opened_resources"` - MysqlOperations MetricSettings `mapstructure:"mysql.operations"` - MysqlPageOperations MetricSettings `mapstructure:"mysql.page_operations"` - MysqlRowLocks MetricSettings `mapstructure:"mysql.row_locks"` - MysqlRowOperations MetricSettings `mapstructure:"mysql.row_operations"` - MysqlSorts MetricSettings `mapstructure:"mysql.sorts"` - MysqlTableIoWaitCount MetricSettings `mapstructure:"mysql.table.io.wait.count"` - MysqlTableIoWaitTime MetricSettings `mapstructure:"mysql.table.io.wait.time"` - MysqlThreads MetricSettings `mapstructure:"mysql.threads"` - MysqlTmpResources MetricSettings `mapstructure:"mysql.tmp_resources"` + MysqlBufferPoolDataPages MetricSettings `mapstructure:"mysql.buffer_pool.data_pages"` + MysqlBufferPoolLimit MetricSettings `mapstructure:"mysql.buffer_pool.limit"` + MysqlBufferPoolOperations MetricSettings `mapstructure:"mysql.buffer_pool.operations"` + MysqlBufferPoolPageFlushes MetricSettings `mapstructure:"mysql.buffer_pool.page_flushes"` + MysqlBufferPoolPages MetricSettings `mapstructure:"mysql.buffer_pool.pages"` + MysqlBufferPoolUsage MetricSettings `mapstructure:"mysql.buffer_pool.usage"` + MysqlCommands MetricSettings `mapstructure:"mysql.commands"` + MysqlDoubleWrites MetricSettings `mapstructure:"mysql.double_writes"` + MysqlHandlers MetricSettings `mapstructure:"mysql.handlers"` + MysqlIndexIoWaitCount MetricSettings `mapstructure:"mysql.index.io.wait.count"` + MysqlIndexIoWaitTime MetricSettings `mapstructure:"mysql.index.io.wait.time"` + MysqlLockedConnects MetricSettings `mapstructure:"mysql.locked_connects"` + MysqlLocks MetricSettings `mapstructure:"mysql.locks"` + MysqlLogOperations MetricSettings `mapstructure:"mysql.log_operations"` + MysqlMysqlxWorkerThreads MetricSettings `mapstructure:"mysql.mysqlx_worker_threads"` + MysqlOpenedResources MetricSettings `mapstructure:"mysql.opened_resources"` + MysqlOperations MetricSettings `mapstructure:"mysql.operations"` + MysqlPageOperations MetricSettings `mapstructure:"mysql.page_operations"` + MysqlRowLocks MetricSettings `mapstructure:"mysql.row_locks"` + MysqlRowOperations MetricSettings `mapstructure:"mysql.row_operations"` + MysqlSorts MetricSettings `mapstructure:"mysql.sorts"` + MysqlStatementEventCount MetricSettings `mapstructure:"mysql.statement_event.count"` + MysqlStatementEventWaitTime MetricSettings `mapstructure:"mysql.statement_event.wait.time"` + MysqlTableIoWaitCount MetricSettings `mapstructure:"mysql.table.io.wait.count"` + MysqlTableIoWaitTime MetricSettings `mapstructure:"mysql.table.io.wait.time"` + MysqlThreads MetricSettings `mapstructure:"mysql.threads"` + MysqlTmpResources MetricSettings `mapstructure:"mysql.tmp_resources"` } func DefaultMetricsSettings() MetricsSettings { @@ -111,6 +113,12 @@ func DefaultMetricsSettings() MetricsSettings { MysqlSorts: MetricSettings{ Enabled: true, }, + MysqlStatementEventCount: MetricSettings{ + Enabled: false, + }, + MysqlStatementEventWaitTime: MetricSettings{ + Enabled: false, + }, MysqlTableIoWaitCount: MetricSettings{ Enabled: true, }, @@ -296,6 +304,64 @@ var MapAttributeDoubleWrites = map[string]AttributeDoubleWrites{ "writes": AttributeDoubleWritesWrites, } +// AttributeEventState specifies the a value event_state attribute. +type AttributeEventState int + +const ( + _ AttributeEventState = iota + AttributeEventStateErrors + AttributeEventStateWarnings + AttributeEventStateRowsAffected + AttributeEventStateRowsSent + AttributeEventStateRowsExamined + AttributeEventStateCreatedTmpDiskTables + AttributeEventStateCreatedTmpTables + AttributeEventStateSortMergePasses + AttributeEventStateSortRows + AttributeEventStateNoIndexUsed +) + +// String returns the string representation of the AttributeEventState. +func (av AttributeEventState) String() string { + switch av { + case AttributeEventStateErrors: + return "errors" + case AttributeEventStateWarnings: + return "warnings" + case AttributeEventStateRowsAffected: + return "rows_affected" + case AttributeEventStateRowsSent: + return "rows_sent" + case AttributeEventStateRowsExamined: + return "rows_examined" + case AttributeEventStateCreatedTmpDiskTables: + return "created_tmp_disk_tables" + case AttributeEventStateCreatedTmpTables: + return "created_tmp_tables" + case AttributeEventStateSortMergePasses: + return "sort_merge_passes" + case AttributeEventStateSortRows: + return "sort_rows" + case AttributeEventStateNoIndexUsed: + return "no_index_used" + } + return "" +} + +// MapAttributeEventState is a helper map of string to AttributeEventState attribute value. +var MapAttributeEventState = map[string]AttributeEventState{ + "errors": AttributeEventStateErrors, + "warnings": AttributeEventStateWarnings, + "rows_affected": AttributeEventStateRowsAffected, + "rows_sent": AttributeEventStateRowsSent, + "rows_examined": AttributeEventStateRowsExamined, + "created_tmp_disk_tables": AttributeEventStateCreatedTmpDiskTables, + "created_tmp_tables": AttributeEventStateCreatedTmpTables, + "sort_merge_passes": AttributeEventStateSortMergePasses, + "sort_rows": AttributeEventStateSortRows, + "no_index_used": AttributeEventStateNoIndexUsed, +} + // AttributeHandler specifies the a value handler attribute. type AttributeHandler int @@ -1863,6 +1929,117 @@ func newMetricMysqlSorts(settings MetricSettings) metricMysqlSorts { return m } +type metricMysqlStatementEventCount struct { + data pmetric.Metric // data buffer for generated metric. + settings MetricSettings // metric settings provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills mysql.statement_event.count metric with initial data. +func (m *metricMysqlStatementEventCount) init() { + m.data.SetName("mysql.statement_event.count") + m.data.SetDescription("Summary of current and recent statement events.") + m.data.SetUnit("1") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(false) + m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative) + m.data.Sum().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricMysqlStatementEventCount) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, schemaAttributeValue string, digestAttributeValue string, digestTextAttributeValue string, eventStateAttributeValue string) { + if !m.settings.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) + dp.Attributes().PutStr("schema", schemaAttributeValue) + dp.Attributes().PutStr("digest", digestAttributeValue) + dp.Attributes().PutStr("digest_text", digestTextAttributeValue) + dp.Attributes().PutStr("kind", eventStateAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricMysqlStatementEventCount) updateCapacity() { + if m.data.Sum().DataPoints().Len() > m.capacity { + m.capacity = m.data.Sum().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricMysqlStatementEventCount) emit(metrics pmetric.MetricSlice) { + if m.settings.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricMysqlStatementEventCount(settings MetricSettings) metricMysqlStatementEventCount { + m := metricMysqlStatementEventCount{settings: settings} + if settings.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricMysqlStatementEventWaitTime struct { + data pmetric.Metric // data buffer for generated metric. + settings MetricSettings // metric settings provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills mysql.statement_event.wait.time metric with initial data. +func (m *metricMysqlStatementEventWaitTime) init() { + m.data.SetName("mysql.statement_event.wait.time") + m.data.SetDescription("The total wait time of the summarized timed events.") + m.data.SetUnit("ns") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(false) + m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative) + m.data.Sum().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricMysqlStatementEventWaitTime) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, schemaAttributeValue string, digestAttributeValue string, digestTextAttributeValue string) { + if !m.settings.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) + dp.Attributes().PutStr("schema", schemaAttributeValue) + dp.Attributes().PutStr("digest", digestAttributeValue) + dp.Attributes().PutStr("digest_text", digestTextAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricMysqlStatementEventWaitTime) updateCapacity() { + if m.data.Sum().DataPoints().Len() > m.capacity { + m.capacity = m.data.Sum().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricMysqlStatementEventWaitTime) emit(metrics pmetric.MetricSlice) { + if m.settings.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricMysqlStatementEventWaitTime(settings MetricSettings) metricMysqlStatementEventWaitTime { + m := metricMysqlStatementEventWaitTime{settings: settings} + if settings.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + type metricMysqlTableIoWaitCount struct { data pmetric.Metric // data buffer for generated metric. settings MetricSettings // metric settings provided by user. @@ -2082,36 +2259,38 @@ func newMetricMysqlTmpResources(settings MetricSettings) metricMysqlTmpResources // MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations // required to produce metric representation defined in metadata and user settings. type MetricsBuilder struct { - startTime pcommon.Timestamp // start time that will be applied to all recorded data points. - metricsCapacity int // maximum observed number of metrics per resource. - resourceCapacity int // maximum observed number of resource attributes. - metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. - buildInfo component.BuildInfo // contains version information - metricMysqlBufferPoolDataPages metricMysqlBufferPoolDataPages - metricMysqlBufferPoolLimit metricMysqlBufferPoolLimit - metricMysqlBufferPoolOperations metricMysqlBufferPoolOperations - metricMysqlBufferPoolPageFlushes metricMysqlBufferPoolPageFlushes - metricMysqlBufferPoolPages metricMysqlBufferPoolPages - metricMysqlBufferPoolUsage metricMysqlBufferPoolUsage - metricMysqlCommands metricMysqlCommands - metricMysqlDoubleWrites metricMysqlDoubleWrites - metricMysqlHandlers metricMysqlHandlers - metricMysqlIndexIoWaitCount metricMysqlIndexIoWaitCount - metricMysqlIndexIoWaitTime metricMysqlIndexIoWaitTime - metricMysqlLockedConnects metricMysqlLockedConnects - metricMysqlLocks metricMysqlLocks - metricMysqlLogOperations metricMysqlLogOperations - metricMysqlMysqlxWorkerThreads metricMysqlMysqlxWorkerThreads - metricMysqlOpenedResources metricMysqlOpenedResources - metricMysqlOperations metricMysqlOperations - metricMysqlPageOperations metricMysqlPageOperations - metricMysqlRowLocks metricMysqlRowLocks - metricMysqlRowOperations metricMysqlRowOperations - metricMysqlSorts metricMysqlSorts - metricMysqlTableIoWaitCount metricMysqlTableIoWaitCount - metricMysqlTableIoWaitTime metricMysqlTableIoWaitTime - metricMysqlThreads metricMysqlThreads - metricMysqlTmpResources metricMysqlTmpResources + startTime pcommon.Timestamp // start time that will be applied to all recorded data points. + metricsCapacity int // maximum observed number of metrics per resource. + resourceCapacity int // maximum observed number of resource attributes. + metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. + buildInfo component.BuildInfo // contains version information + metricMysqlBufferPoolDataPages metricMysqlBufferPoolDataPages + metricMysqlBufferPoolLimit metricMysqlBufferPoolLimit + metricMysqlBufferPoolOperations metricMysqlBufferPoolOperations + metricMysqlBufferPoolPageFlushes metricMysqlBufferPoolPageFlushes + metricMysqlBufferPoolPages metricMysqlBufferPoolPages + metricMysqlBufferPoolUsage metricMysqlBufferPoolUsage + metricMysqlCommands metricMysqlCommands + metricMysqlDoubleWrites metricMysqlDoubleWrites + metricMysqlHandlers metricMysqlHandlers + metricMysqlIndexIoWaitCount metricMysqlIndexIoWaitCount + metricMysqlIndexIoWaitTime metricMysqlIndexIoWaitTime + metricMysqlLockedConnects metricMysqlLockedConnects + metricMysqlLocks metricMysqlLocks + metricMysqlLogOperations metricMysqlLogOperations + metricMysqlMysqlxWorkerThreads metricMysqlMysqlxWorkerThreads + metricMysqlOpenedResources metricMysqlOpenedResources + metricMysqlOperations metricMysqlOperations + metricMysqlPageOperations metricMysqlPageOperations + metricMysqlRowLocks metricMysqlRowLocks + metricMysqlRowOperations metricMysqlRowOperations + metricMysqlSorts metricMysqlSorts + metricMysqlStatementEventCount metricMysqlStatementEventCount + metricMysqlStatementEventWaitTime metricMysqlStatementEventWaitTime + metricMysqlTableIoWaitCount metricMysqlTableIoWaitCount + metricMysqlTableIoWaitTime metricMysqlTableIoWaitTime + metricMysqlThreads metricMysqlThreads + metricMysqlTmpResources metricMysqlTmpResources } // metricBuilderOption applies changes to default metrics builder. @@ -2126,34 +2305,36 @@ func WithStartTime(startTime pcommon.Timestamp) metricBuilderOption { func NewMetricsBuilder(settings MetricsSettings, buildInfo component.BuildInfo, options ...metricBuilderOption) *MetricsBuilder { mb := &MetricsBuilder{ - startTime: pcommon.NewTimestampFromTime(time.Now()), - metricsBuffer: pmetric.NewMetrics(), - buildInfo: buildInfo, - metricMysqlBufferPoolDataPages: newMetricMysqlBufferPoolDataPages(settings.MysqlBufferPoolDataPages), - metricMysqlBufferPoolLimit: newMetricMysqlBufferPoolLimit(settings.MysqlBufferPoolLimit), - metricMysqlBufferPoolOperations: newMetricMysqlBufferPoolOperations(settings.MysqlBufferPoolOperations), - metricMysqlBufferPoolPageFlushes: newMetricMysqlBufferPoolPageFlushes(settings.MysqlBufferPoolPageFlushes), - metricMysqlBufferPoolPages: newMetricMysqlBufferPoolPages(settings.MysqlBufferPoolPages), - metricMysqlBufferPoolUsage: newMetricMysqlBufferPoolUsage(settings.MysqlBufferPoolUsage), - metricMysqlCommands: newMetricMysqlCommands(settings.MysqlCommands), - metricMysqlDoubleWrites: newMetricMysqlDoubleWrites(settings.MysqlDoubleWrites), - metricMysqlHandlers: newMetricMysqlHandlers(settings.MysqlHandlers), - metricMysqlIndexIoWaitCount: newMetricMysqlIndexIoWaitCount(settings.MysqlIndexIoWaitCount), - metricMysqlIndexIoWaitTime: newMetricMysqlIndexIoWaitTime(settings.MysqlIndexIoWaitTime), - metricMysqlLockedConnects: newMetricMysqlLockedConnects(settings.MysqlLockedConnects), - metricMysqlLocks: newMetricMysqlLocks(settings.MysqlLocks), - metricMysqlLogOperations: newMetricMysqlLogOperations(settings.MysqlLogOperations), - metricMysqlMysqlxWorkerThreads: newMetricMysqlMysqlxWorkerThreads(settings.MysqlMysqlxWorkerThreads), - metricMysqlOpenedResources: newMetricMysqlOpenedResources(settings.MysqlOpenedResources), - metricMysqlOperations: newMetricMysqlOperations(settings.MysqlOperations), - metricMysqlPageOperations: newMetricMysqlPageOperations(settings.MysqlPageOperations), - metricMysqlRowLocks: newMetricMysqlRowLocks(settings.MysqlRowLocks), - metricMysqlRowOperations: newMetricMysqlRowOperations(settings.MysqlRowOperations), - metricMysqlSorts: newMetricMysqlSorts(settings.MysqlSorts), - metricMysqlTableIoWaitCount: newMetricMysqlTableIoWaitCount(settings.MysqlTableIoWaitCount), - metricMysqlTableIoWaitTime: newMetricMysqlTableIoWaitTime(settings.MysqlTableIoWaitTime), - metricMysqlThreads: newMetricMysqlThreads(settings.MysqlThreads), - metricMysqlTmpResources: newMetricMysqlTmpResources(settings.MysqlTmpResources), + startTime: pcommon.NewTimestampFromTime(time.Now()), + metricsBuffer: pmetric.NewMetrics(), + buildInfo: buildInfo, + metricMysqlBufferPoolDataPages: newMetricMysqlBufferPoolDataPages(settings.MysqlBufferPoolDataPages), + metricMysqlBufferPoolLimit: newMetricMysqlBufferPoolLimit(settings.MysqlBufferPoolLimit), + metricMysqlBufferPoolOperations: newMetricMysqlBufferPoolOperations(settings.MysqlBufferPoolOperations), + metricMysqlBufferPoolPageFlushes: newMetricMysqlBufferPoolPageFlushes(settings.MysqlBufferPoolPageFlushes), + metricMysqlBufferPoolPages: newMetricMysqlBufferPoolPages(settings.MysqlBufferPoolPages), + metricMysqlBufferPoolUsage: newMetricMysqlBufferPoolUsage(settings.MysqlBufferPoolUsage), + metricMysqlCommands: newMetricMysqlCommands(settings.MysqlCommands), + metricMysqlDoubleWrites: newMetricMysqlDoubleWrites(settings.MysqlDoubleWrites), + metricMysqlHandlers: newMetricMysqlHandlers(settings.MysqlHandlers), + metricMysqlIndexIoWaitCount: newMetricMysqlIndexIoWaitCount(settings.MysqlIndexIoWaitCount), + metricMysqlIndexIoWaitTime: newMetricMysqlIndexIoWaitTime(settings.MysqlIndexIoWaitTime), + metricMysqlLockedConnects: newMetricMysqlLockedConnects(settings.MysqlLockedConnects), + metricMysqlLocks: newMetricMysqlLocks(settings.MysqlLocks), + metricMysqlLogOperations: newMetricMysqlLogOperations(settings.MysqlLogOperations), + metricMysqlMysqlxWorkerThreads: newMetricMysqlMysqlxWorkerThreads(settings.MysqlMysqlxWorkerThreads), + metricMysqlOpenedResources: newMetricMysqlOpenedResources(settings.MysqlOpenedResources), + metricMysqlOperations: newMetricMysqlOperations(settings.MysqlOperations), + metricMysqlPageOperations: newMetricMysqlPageOperations(settings.MysqlPageOperations), + metricMysqlRowLocks: newMetricMysqlRowLocks(settings.MysqlRowLocks), + metricMysqlRowOperations: newMetricMysqlRowOperations(settings.MysqlRowOperations), + metricMysqlSorts: newMetricMysqlSorts(settings.MysqlSorts), + metricMysqlStatementEventCount: newMetricMysqlStatementEventCount(settings.MysqlStatementEventCount), + metricMysqlStatementEventWaitTime: newMetricMysqlStatementEventWaitTime(settings.MysqlStatementEventWaitTime), + metricMysqlTableIoWaitCount: newMetricMysqlTableIoWaitCount(settings.MysqlTableIoWaitCount), + metricMysqlTableIoWaitTime: newMetricMysqlTableIoWaitTime(settings.MysqlTableIoWaitTime), + metricMysqlThreads: newMetricMysqlThreads(settings.MysqlThreads), + metricMysqlTmpResources: newMetricMysqlTmpResources(settings.MysqlTmpResources), } for _, op := range options { op(mb) @@ -2234,6 +2415,8 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { mb.metricMysqlRowLocks.emit(ils.Metrics()) mb.metricMysqlRowOperations.emit(ils.Metrics()) mb.metricMysqlSorts.emit(ils.Metrics()) + mb.metricMysqlStatementEventCount.emit(ils.Metrics()) + mb.metricMysqlStatementEventWaitTime.emit(ils.Metrics()) mb.metricMysqlTableIoWaitCount.emit(ils.Metrics()) mb.metricMysqlTableIoWaitTime.emit(ils.Metrics()) mb.metricMysqlThreads.emit(ils.Metrics()) @@ -2447,6 +2630,16 @@ func (mb *MetricsBuilder) RecordMysqlSortsDataPoint(ts pcommon.Timestamp, inputV return nil } +// RecordMysqlStatementEventCountDataPoint adds a data point to mysql.statement_event.count metric. +func (mb *MetricsBuilder) RecordMysqlStatementEventCountDataPoint(ts pcommon.Timestamp, val int64, schemaAttributeValue string, digestAttributeValue string, digestTextAttributeValue string, eventStateAttributeValue AttributeEventState) { + mb.metricMysqlStatementEventCount.recordDataPoint(mb.startTime, ts, val, schemaAttributeValue, digestAttributeValue, digestTextAttributeValue, eventStateAttributeValue.String()) +} + +// RecordMysqlStatementEventWaitTimeDataPoint adds a data point to mysql.statement_event.wait.time metric. +func (mb *MetricsBuilder) RecordMysqlStatementEventWaitTimeDataPoint(ts pcommon.Timestamp, val int64, schemaAttributeValue string, digestAttributeValue string, digestTextAttributeValue string) { + mb.metricMysqlStatementEventWaitTime.recordDataPoint(mb.startTime, ts, val, schemaAttributeValue, digestAttributeValue, digestTextAttributeValue) +} + // RecordMysqlTableIoWaitCountDataPoint adds a data point to mysql.table.io.wait.count metric. func (mb *MetricsBuilder) RecordMysqlTableIoWaitCountDataPoint(ts pcommon.Timestamp, val int64, ioWaitsOperationsAttributeValue AttributeIoWaitsOperations, tableNameAttributeValue string, schemaAttributeValue string) { mb.metricMysqlTableIoWaitCount.recordDataPoint(mb.startTime, ts, val, ioWaitsOperationsAttributeValue.String(), tableNameAttributeValue, schemaAttributeValue) diff --git a/receiver/mysqlreceiver/metadata.yaml b/receiver/mysqlreceiver/metadata.yaml index 9e39d7d0f1b8..c3727fe92c37 100644 --- a/receiver/mysqlreceiver/metadata.yaml +++ b/receiver/mysqlreceiver/metadata.yaml @@ -75,6 +75,16 @@ attributes: index_name: value: index description: The name of the index. + digest: + value: digest + description: Digest. + digest_text: + value: digest_text + description: Text before digestion. + event_state: + value: kind + description: Possible event states. + enum: [errors, warnings, rows_affected, rows_sent, rows_examined, created_tmp_disk_tables, created_tmp_tables, sort_merge_passes, sort_rows, no_index_used] opened_resources: value: kind description: The kind of the resource. @@ -320,6 +330,24 @@ metrics: monotonic: true aggregation: cumulative attributes: [tmp_resource] + mysql.statement_event.count: + enabled: false + description: Summary of current and recent statement events. + unit: 1 + sum: + value_type: int + monotonic: false + aggregation: cumulative + attributes: [schema, digest, digest_text, event_state] + mysql.statement_event.wait.time: + enabled: false + description: The total wait time of the summarized timed events. + unit: ns + sum: + value_type: int + monotonic: false + aggregation: cumulative + attributes: [schema, digest, digest_text] mysql.mysqlx_worker_threads: enabled: true description: The number of worker threads available. diff --git a/receiver/mysqlreceiver/scraper.go b/receiver/mysqlreceiver/scraper.go index 9336d1a8f666..c69296cbca74 100644 --- a/receiver/mysqlreceiver/scraper.go +++ b/receiver/mysqlreceiver/scraper.go @@ -98,6 +98,9 @@ func (m *mySQLScraper) scrape(context.Context) (pmetric.Metrics, error) { m.scrapeTableIoWaitsStats(now, errs) m.scrapeIndexIoWaitsStats(now, errs) + // collect performance event statements metrics. + m.scrapeStatementEventsStats(now, errs) + // collect global status metrics. m.scrapeGlobalStats(now, errs) @@ -379,6 +382,31 @@ func (m *mySQLScraper) scrapeIndexIoWaitsStats(now pcommon.Timestamp, errs *scra } } +func (m *mySQLScraper) scrapeStatementEventsStats(now pcommon.Timestamp, errs *scrapererror.ScrapeErrors) { + statementEventsStats, err := m.sqlclient.getStatementEventsStats() + if err != nil { + m.logger.Error("Failed to fetch index io_waits stats", zap.Error(err)) + errs.AddPartial(8, err) + return + } + + for i := 0; i < len(statementEventsStats); i++ { + s := statementEventsStats[i] + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countCreatedTmpDiskTables, s.schema, s.digest, s.digestText, metadata.AttributeEventStateCreatedTmpDiskTables) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countCreatedTmpTables, s.schema, s.digest, s.digestText, metadata.AttributeEventStateCreatedTmpTables) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countErrors, s.schema, s.digest, s.digestText, metadata.AttributeEventStateErrors) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countNoIndexUsed, s.schema, s.digest, s.digestText, metadata.AttributeEventStateNoIndexUsed) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countRowsAffected, s.schema, s.digest, s.digestText, metadata.AttributeEventStateRowsAffected) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countRowsExamined, s.schema, s.digest, s.digestText, metadata.AttributeEventStateRowsExamined) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countRowsSent, s.schema, s.digest, s.digestText, metadata.AttributeEventStateRowsSent) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countSortMergePasses, s.schema, s.digest, s.digestText, metadata.AttributeEventStateSortMergePasses) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countSortRows, s.schema, s.digest, s.digestText, metadata.AttributeEventStateSortRows) + m.mb.RecordMysqlStatementEventCountDataPoint(now, s.countWarnings, s.schema, s.digest, s.digestText, metadata.AttributeEventStateWarnings) + + m.mb.RecordMysqlStatementEventWaitTimeDataPoint(now, s.sumTimerWait/picosecondsInNanoseconds, s.schema, s.digest, s.digestText) + } +} + func addPartialIfError(errors *scrapererror.ScrapeErrors, err error) { if err != nil { errors.AddPartial(1, err) diff --git a/receiver/mysqlreceiver/scraper_test.go b/receiver/mysqlreceiver/scraper_test.go index b6a940d7436b..0ca70bfe22be 100644 --- a/receiver/mysqlreceiver/scraper_test.go +++ b/receiver/mysqlreceiver/scraper_test.go @@ -39,13 +39,16 @@ func TestScrape(t *testing.T) { cfg.Username = "otel" cfg.Password = "otel" cfg.NetAddr = confignet.NetAddr{Endpoint: "localhost:3306"} + cfg.Metrics.MysqlStatementEventCount.Enabled = true + cfg.Metrics.MysqlStatementEventWaitTime.Enabled = true scraper := newMySQLScraper(componenttest.NewNopReceiverCreateSettings(), cfg) scraper.sqlclient = &mockClient{ - globalStatsFile: "global_stats", - innodbStatsFile: "innodb_stats", - tableIoWaitsFile: "table_io_waits_stats", - indexIoWaitsFile: "index_io_waits_stats", + globalStatsFile: "global_stats", + innodbStatsFile: "innodb_stats", + tableIoWaitsFile: "table_io_waits_stats", + indexIoWaitsFile: "index_io_waits_stats", + statementEventsFile: "statement_events", } actualMetrics, err := scraper.scrape(context.Background()) @@ -66,10 +69,11 @@ func TestScrape(t *testing.T) { scraper := newMySQLScraper(componenttest.NewNopReceiverCreateSettings(), cfg) scraper.sqlclient = &mockClient{ - globalStatsFile: "global_stats_partial", - innodbStatsFile: "innodb_stats_empty", - tableIoWaitsFile: "table_io_waits_stats_empty", - indexIoWaitsFile: "index_io_waits_stats_empty", + globalStatsFile: "global_stats_partial", + innodbStatsFile: "innodb_stats_empty", + tableIoWaitsFile: "table_io_waits_stats_empty", + indexIoWaitsFile: "index_io_waits_stats_empty", + statementEventsFile: "statement_events_empty", } actualMetrics, scrapeErr := scraper.scrape(context.Background()) @@ -92,10 +96,11 @@ func TestScrape(t *testing.T) { var _ client = (*mockClient)(nil) type mockClient struct { - globalStatsFile string - innodbStatsFile string - tableIoWaitsFile string - indexIoWaitsFile string + globalStatsFile string + innodbStatsFile string + tableIoWaitsFile string + indexIoWaitsFile string + statementEventsFile string } func readFile(fname string) (map[string]string, error) { @@ -185,6 +190,39 @@ func (c *mockClient) getIndexIoWaitsStats() ([]IndexIoWaitsStats, error) { return stats, nil } +func (c *mockClient) getStatementEventsStats() ([]StatementEventStats, error) { + var stats []StatementEventStats + file, err := os.Open(filepath.Join("testdata", "scraper", c.statementEventsFile+".txt")) + if err != nil { + return nil, err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + var s StatementEventStats + text := strings.Split(scanner.Text(), "\t") + + s.schema = text[0] + s.digest = text[1] + s.digestText = text[2] + s.sumTimerWait, _ = parseInt(text[3]) + s.countErrors, _ = parseInt(text[4]) + s.countWarnings, _ = parseInt(text[5]) + s.countRowsAffected, _ = parseInt(text[6]) + s.countRowsSent, _ = parseInt(text[7]) + s.countRowsExamined, _ = parseInt(text[8]) + s.countCreatedTmpDiskTables, _ = parseInt(text[9]) + s.countCreatedTmpTables, _ = parseInt(text[10]) + s.countSortMergePasses, _ = parseInt(text[11]) + s.countSortRows, _ = parseInt(text[12]) + s.countNoIndexUsed, _ = parseInt(text[13]) + + stats = append(stats, s) + } + return stats, nil +} + func (c *mockClient) Close() error { return nil } diff --git a/receiver/mysqlreceiver/testdata/scraper/expected.json b/receiver/mysqlreceiver/testdata/scraper/expected.json index 2653251f0a4f..cc7b093b32b7 100644 --- a/receiver/mysqlreceiver/testdata/scraper/expected.json +++ b/receiver/mysqlreceiver/testdata/scraper/expected.json @@ -1537,6 +1537,361 @@ }, "unit": "ns" }, + { + "description": "Summary of current and recent statement events.", + "name": "mysql.statement_event.count", + "sum": { + "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", + "dataPoints": [ + { + "asInt": "8", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "created_tmp_disk_tables" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "9", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "created_tmp_tables" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "3", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "errors" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "12", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "no_index_used" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "5", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "rows_affected" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "7", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "rows_examined" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "6", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "rows_sent" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "10", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "sort_merge_passes" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "11", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "sort_rows" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + }, + { + "asInt": "4", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "kind", + "value": { + "stringValue": "warnings" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + } + ] + }, + "unit": "1" + }, + { + "description": "The total wait time of the summarized timed events.", + "name": "mysql.statement_event.wait.time", + "sum": { + "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", + "dataPoints": [ + { + "asInt": "2", + "attributes": [ + { + "key": "digest", + "value": { + "stringValue": "070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317" + } + }, + { + "key": "digest_text", + "value": { + "stringValue": "SHOW GLOBAL STATUS" + } + }, + { + "key": "schema", + "value": { + "stringValue": "otel" + } + } + ], + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + } + ] + }, + "unit": "ns" + }, { "description": "The number of worker threads available.", "name": "mysql.mysqlx_worker_threads", diff --git a/receiver/mysqlreceiver/testdata/scraper/statement_events.txt b/receiver/mysqlreceiver/testdata/scraper/statement_events.txt new file mode 100644 index 000000000000..fd49b0d4058e --- /dev/null +++ b/receiver/mysqlreceiver/testdata/scraper/statement_events.txt @@ -0,0 +1 @@ +otel 070e38632eb4444e50cdcbf0b17474ba801e203add89783a24584951442a2317 SHOW GLOBAL STATUS 2000 3 4 5 6 7 8 9 10 11 12 diff --git a/receiver/mysqlreceiver/testdata/scraper/statement_events_empty.txt b/receiver/mysqlreceiver/testdata/scraper/statement_events_empty.txt new file mode 100644 index 000000000000..e69de29bb2d1