From acf34ed52336584ed2fecd927af699d4169dd22c Mon Sep 17 00:00:00 2001 From: Dominik Rosiek Date: Thu, 6 Oct 2022 09:26:38 +0200 Subject: [PATCH] feat(mysqlreceiver): add mysql queries (all, client and slow) count metrics Signed-off-by: Dominik Rosiek --- .chloggen/drosiek-mysql-questions.yaml | 16 ++ receiver/mysqlreceiver/documentation.md | 3 + .../internal/metadata/generated_metrics.go | 204 ++++++++++++++++++ receiver/mysqlreceiver/metadata.yaml | 27 +++ receiver/mysqlreceiver/scraper.go | 8 + .../testdata/scraper/expected.json | 48 +++++ 6 files changed, 306 insertions(+) create mode 100755 .chloggen/drosiek-mysql-questions.yaml diff --git a/.chloggen/drosiek-mysql-questions.yaml b/.chloggen/drosiek-mysql-questions.yaml new file mode 100755 index 000000000000..46a1d9278823 --- /dev/null +++ b/.chloggen/drosiek-mysql-questions.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: mysqlreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: add mysql queries (all, client and slow) count metrics + +# 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/documentation.md b/receiver/mysqlreceiver/documentation.md index d5d9216cf649..adaf9a4ea35c 100644 --- a/receiver/mysqlreceiver/documentation.md +++ b/receiver/mysqlreceiver/documentation.md @@ -23,6 +23,9 @@ These are the metrics available for this scraper. | **mysql.log_operations** | The number of InnoDB log operations. | 1 | Sum(Int) | | | **mysql.operations** | The number of InnoDB operations. | 1 | Sum(Int) | | | **mysql.page_operations** | The number of InnoDB page operations. | 1 | Sum(Int) | | +| **mysql.queries.client.count** | The number of statements executed by the server. This includes only statements sent to the server by clients. | 1 | Sum(Int) | | +| **mysql.queries.count** | The number of statements executed by the server. | 1 | Sum(Int) | | +| **mysql.queries.slow.count** | The number of slow queries. | 1 | Sum(Int) | | | **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) | | diff --git a/receiver/mysqlreceiver/internal/metadata/generated_metrics.go b/receiver/mysqlreceiver/internal/metadata/generated_metrics.go index 71a4d9387252..3b55ac07fe24 100644 --- a/receiver/mysqlreceiver/internal/metadata/generated_metrics.go +++ b/receiver/mysqlreceiver/internal/metadata/generated_metrics.go @@ -34,6 +34,9 @@ type MetricsSettings struct { MysqlLogOperations MetricSettings `mapstructure:"mysql.log_operations"` MysqlOperations MetricSettings `mapstructure:"mysql.operations"` MysqlPageOperations MetricSettings `mapstructure:"mysql.page_operations"` + MysqlQueriesClientCount MetricSettings `mapstructure:"mysql.queries.client.count"` + MysqlQueriesCount MetricSettings `mapstructure:"mysql.queries.count"` + MysqlQueriesSlowCount MetricSettings `mapstructure:"mysql.queries.slow.count"` MysqlRowLocks MetricSettings `mapstructure:"mysql.row_locks"` MysqlRowOperations MetricSettings `mapstructure:"mysql.row_operations"` MysqlSorts MetricSettings `mapstructure:"mysql.sorts"` @@ -89,6 +92,15 @@ func DefaultMetricsSettings() MetricsSettings { MysqlPageOperations: MetricSettings{ Enabled: true, }, + MysqlQueriesClientCount: MetricSettings{ + Enabled: true, + }, + MysqlQueriesCount: MetricSettings{ + Enabled: true, + }, + MysqlQueriesSlowCount: MetricSettings{ + Enabled: true, + }, MysqlRowLocks: MetricSettings{ Enabled: true, }, @@ -1445,6 +1457,159 @@ func newMetricMysqlPageOperations(settings MetricSettings) metricMysqlPageOperat return m } +type metricMysqlQueriesClientCount 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.queries.client.count metric with initial data. +func (m *metricMysqlQueriesClientCount) init() { + m.data.SetName("mysql.queries.client.count") + m.data.SetDescription("The number of statements executed by the server. This includes only statements sent to the server by clients.") + m.data.SetUnit("1") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(true) + m.data.Sum().SetAggregationTemporality(pmetric.MetricAggregationTemporalityCumulative) +} + +func (m *metricMysqlQueriesClientCount) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64) { + if !m.settings.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricMysqlQueriesClientCount) 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 *metricMysqlQueriesClientCount) emit(metrics pmetric.MetricSlice) { + if m.settings.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricMysqlQueriesClientCount(settings MetricSettings) metricMysqlQueriesClientCount { + m := metricMysqlQueriesClientCount{settings: settings} + if settings.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricMysqlQueriesCount 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.queries.count metric with initial data. +func (m *metricMysqlQueriesCount) init() { + m.data.SetName("mysql.queries.count") + m.data.SetDescription("The number of statements executed by the server.") + m.data.SetUnit("1") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(true) + m.data.Sum().SetAggregationTemporality(pmetric.MetricAggregationTemporalityCumulative) +} + +func (m *metricMysqlQueriesCount) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64) { + if !m.settings.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricMysqlQueriesCount) 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 *metricMysqlQueriesCount) emit(metrics pmetric.MetricSlice) { + if m.settings.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricMysqlQueriesCount(settings MetricSettings) metricMysqlQueriesCount { + m := metricMysqlQueriesCount{settings: settings} + if settings.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricMysqlQueriesSlowCount 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.queries.slow.count metric with initial data. +func (m *metricMysqlQueriesSlowCount) init() { + m.data.SetName("mysql.queries.slow.count") + m.data.SetDescription("The number of slow queries.") + m.data.SetUnit("1") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(true) + m.data.Sum().SetAggregationTemporality(pmetric.MetricAggregationTemporalityCumulative) +} + +func (m *metricMysqlQueriesSlowCount) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64) { + if !m.settings.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricMysqlQueriesSlowCount) 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 *metricMysqlQueriesSlowCount) emit(metrics pmetric.MetricSlice) { + if m.settings.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricMysqlQueriesSlowCount(settings MetricSettings) metricMysqlQueriesSlowCount { + m := metricMysqlQueriesSlowCount{settings: settings} + if settings.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + type metricMysqlRowLocks struct { data pmetric.Metric // data buffer for generated metric. settings MetricSettings // metric settings provided by user. @@ -1790,6 +1955,9 @@ type MetricsBuilder struct { metricMysqlLogOperations metricMysqlLogOperations metricMysqlOperations metricMysqlOperations metricMysqlPageOperations metricMysqlPageOperations + metricMysqlQueriesClientCount metricMysqlQueriesClientCount + metricMysqlQueriesCount metricMysqlQueriesCount + metricMysqlQueriesSlowCount metricMysqlQueriesSlowCount metricMysqlRowLocks metricMysqlRowLocks metricMysqlRowOperations metricMysqlRowOperations metricMysqlSorts metricMysqlSorts @@ -1828,6 +1996,9 @@ func NewMetricsBuilder(settings MetricsSettings, buildInfo component.BuildInfo, metricMysqlLogOperations: newMetricMysqlLogOperations(settings.MysqlLogOperations), metricMysqlOperations: newMetricMysqlOperations(settings.MysqlOperations), metricMysqlPageOperations: newMetricMysqlPageOperations(settings.MysqlPageOperations), + metricMysqlQueriesClientCount: newMetricMysqlQueriesClientCount(settings.MysqlQueriesClientCount), + metricMysqlQueriesCount: newMetricMysqlQueriesCount(settings.MysqlQueriesCount), + metricMysqlQueriesSlowCount: newMetricMysqlQueriesSlowCount(settings.MysqlQueriesSlowCount), metricMysqlRowLocks: newMetricMysqlRowLocks(settings.MysqlRowLocks), metricMysqlRowOperations: newMetricMysqlRowOperations(settings.MysqlRowOperations), metricMysqlSorts: newMetricMysqlSorts(settings.MysqlSorts), @@ -1908,6 +2079,9 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { mb.metricMysqlLogOperations.emit(ils.Metrics()) mb.metricMysqlOperations.emit(ils.Metrics()) mb.metricMysqlPageOperations.emit(ils.Metrics()) + mb.metricMysqlQueriesClientCount.emit(ils.Metrics()) + mb.metricMysqlQueriesCount.emit(ils.Metrics()) + mb.metricMysqlQueriesSlowCount.emit(ils.Metrics()) mb.metricMysqlRowLocks.emit(ils.Metrics()) mb.metricMysqlRowOperations.emit(ils.Metrics()) mb.metricMysqlSorts.emit(ils.Metrics()) @@ -2063,6 +2237,36 @@ func (mb *MetricsBuilder) RecordMysqlPageOperationsDataPoint(ts pcommon.Timestam return nil } +// RecordMysqlQueriesClientCountDataPoint adds a data point to mysql.queries.client.count metric. +func (mb *MetricsBuilder) RecordMysqlQueriesClientCountDataPoint(ts pcommon.Timestamp, inputVal string) error { + val, err := strconv.ParseInt(inputVal, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int64 for MysqlQueriesClientCount, value was %s: %w", inputVal, err) + } + mb.metricMysqlQueriesClientCount.recordDataPoint(mb.startTime, ts, val) + return nil +} + +// RecordMysqlQueriesCountDataPoint adds a data point to mysql.queries.count metric. +func (mb *MetricsBuilder) RecordMysqlQueriesCountDataPoint(ts pcommon.Timestamp, inputVal string) error { + val, err := strconv.ParseInt(inputVal, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int64 for MysqlQueriesCount, value was %s: %w", inputVal, err) + } + mb.metricMysqlQueriesCount.recordDataPoint(mb.startTime, ts, val) + return nil +} + +// RecordMysqlQueriesSlowCountDataPoint adds a data point to mysql.queries.slow.count metric. +func (mb *MetricsBuilder) RecordMysqlQueriesSlowCountDataPoint(ts pcommon.Timestamp, inputVal string) error { + val, err := strconv.ParseInt(inputVal, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int64 for MysqlQueriesSlowCount, value was %s: %w", inputVal, err) + } + mb.metricMysqlQueriesSlowCount.recordDataPoint(mb.startTime, ts, val) + return nil +} + // RecordMysqlRowLocksDataPoint adds a data point to mysql.row_locks metric. func (mb *MetricsBuilder) RecordMysqlRowLocksDataPoint(ts pcommon.Timestamp, inputVal string, rowLocksAttributeValue AttributeRowLocks) error { val, err := strconv.ParseInt(inputVal, 10, 64) diff --git a/receiver/mysqlreceiver/metadata.yaml b/receiver/mysqlreceiver/metadata.yaml index 65e5fa79780e..259db2c85902 100644 --- a/receiver/mysqlreceiver/metadata.yaml +++ b/receiver/mysqlreceiver/metadata.yaml @@ -279,3 +279,30 @@ metrics: monotonic: false aggregation: cumulative attributes: [threads] + mysql.queries.client.count: + enabled: true + description: The number of statements executed by the server. This includes only statements sent to the server by clients. + unit: 1 + sum: + value_type: int + input_type: string + monotonic: true + aggregation: cumulative + mysql.queries.count: + enabled: true + description: The number of statements executed by the server. + unit: 1 + sum: + value_type: int + input_type: string + monotonic: true + aggregation: cumulative + mysql.queries.slow.count: + enabled: true + description: The number of slow queries. + unit: 1 + sum: + value_type: int + input_type: string + monotonic: true + aggregation: cumulative diff --git a/receiver/mysqlreceiver/scraper.go b/receiver/mysqlreceiver/scraper.go index 18652b9715f2..75a57955d780 100644 --- a/receiver/mysqlreceiver/scraper.go +++ b/receiver/mysqlreceiver/scraper.go @@ -266,6 +266,14 @@ func (m *mySQLScraper) scrapeGlobalStats(now pcommon.Timestamp, errs *scrapererr case "Table_locks_waited": addPartialIfError(errs, m.mb.RecordMysqlLocksDataPoint(now, v, metadata.AttributeLocksWaited)) + // queries + case "Queries": + addPartialIfError(errs, m.mb.RecordMysqlQueriesCountDataPoint(now, v)) + case "Questions": + addPartialIfError(errs, m.mb.RecordMysqlQueriesClientCountDataPoint(now, v)) + case "Slow_queries": + addPartialIfError(errs, m.mb.RecordMysqlQueriesSlowCountDataPoint(now, v)) + // sorts case "Sort_merge_passes": addPartialIfError(errs, m.mb.RecordMysqlSortsDataPoint(now, v, metadata.AttributeSortsMergePasses)) diff --git a/receiver/mysqlreceiver/testdata/scraper/expected.json b/receiver/mysqlreceiver/testdata/scraper/expected.json index 74d262e04c72..701bba588162 100644 --- a/receiver/mysqlreceiver/testdata/scraper/expected.json +++ b/receiver/mysqlreceiver/testdata/scraper/expected.json @@ -1536,6 +1536,54 @@ ] }, "unit": "ns" + }, + { + "description": "The number of statements executed by the server. This includes only statements sent to the server by clients.", + "name": "mysql.queries.client.count", + "sum": { + "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", + "dataPoints": [ + { + "asInt": "407", + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + } + ], + "isMonotonic": true + }, + "unit": "1" + }, + { + "description": "The number of statements executed by the server.", + "name": "mysql.queries.count", + "sum": { + "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", + "dataPoints": [ + { + "asInt": "406", + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + } + ], + "isMonotonic": true + }, + "unit": "1" + }, + { + "description": "The number of slow queries.", + "name": "mysql.queries.slow.count", + "sum": { + "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", + "dataPoints": [ + { + "asInt": "415", + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + } + ], + "isMonotonic": true + }, + "unit": "1" } ] }