From fd4b221e1f2f6ec9adaf2f66738b585967f05ec1 Mon Sep 17 00:00:00 2001 From: Dominik Rosiek <58699848+sumo-drosiek@users.noreply.github.com> Date: Fri, 7 Oct 2022 17:13:15 +0200 Subject: [PATCH] [receiver/mysql]: add mysql.locked_connects metric (#14745) feat(mysqlreceiver): add mysql.locked_connects metric --- ...drosiek-uptime-innodb-row-lock-metric.yaml | 16 +++++ receiver/mysqlreceiver/documentation.md | 1 + .../internal/metadata/generated_metrics.go | 68 +++++++++++++++++++ receiver/mysqlreceiver/metadata.yaml | 9 +++ receiver/mysqlreceiver/scraper.go | 4 ++ .../testdata/scraper/expected.json | 16 +++++ 6 files changed, 114 insertions(+) create mode 100755 .chloggen/drosiek-uptime-innodb-row-lock-metric.yaml diff --git a/.chloggen/drosiek-uptime-innodb-row-lock-metric.yaml b/.chloggen/drosiek-uptime-innodb-row-lock-metric.yaml new file mode 100755 index 000000000000..b3c85b33efb6 --- /dev/null +++ b/.chloggen/drosiek-uptime-innodb-row-lock-metric.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.locked_connects metric + +# 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 9b35170ee455..7f9a58f3d265 100644 --- a/receiver/mysqlreceiver/documentation.md +++ b/receiver/mysqlreceiver/documentation.md @@ -19,6 +19,7 @@ These are the metrics available for this scraper. | **mysql.handlers** | The number of requests to various MySQL handlers. | 1 | Sum(Int) | | | **mysql.index.io.wait.count** | The total count of I/O wait events for an index. | 1 | Sum(Int) | | | **mysql.index.io.wait.time** | The total time of I/O wait events for an index. | ns | Sum(Int) | | +| **mysql.locked_connects** | The number of attempts to connect to locked user accounts. | 1 | Sum(Int) | | | **mysql.locks** | The number of MySQL locks. | 1 | Sum(Int) | | | **mysql.log_operations** | The number of InnoDB log operations. | 1 | Sum(Int) | | | **mysql.operations** | The number of InnoDB operations. | 1 | Sum(Int) | | diff --git a/receiver/mysqlreceiver/internal/metadata/generated_metrics.go b/receiver/mysqlreceiver/internal/metadata/generated_metrics.go index bd607f400d3c..10968cbf18ff 100644 --- a/receiver/mysqlreceiver/internal/metadata/generated_metrics.go +++ b/receiver/mysqlreceiver/internal/metadata/generated_metrics.go @@ -30,6 +30,7 @@ type MetricsSettings struct { 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"` MysqlOperations MetricSettings `mapstructure:"mysql.operations"` @@ -78,6 +79,9 @@ func DefaultMetricsSettings() MetricsSettings { MysqlIndexIoWaitTime: MetricSettings{ Enabled: true, }, + MysqlLockedConnects: MetricSettings{ + Enabled: true, + }, MysqlLocks: MetricSettings{ Enabled: true, }, @@ -1267,6 +1271,57 @@ func newMetricMysqlIndexIoWaitTime(settings MetricSettings) metricMysqlIndexIoWa return m } +type metricMysqlLockedConnects 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.locked_connects metric with initial data. +func (m *metricMysqlLockedConnects) init() { + m.data.SetName("mysql.locked_connects") + m.data.SetDescription("The number of attempts to connect to locked user accounts.") + m.data.SetUnit("1") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(true) + m.data.Sum().SetAggregationTemporality(pmetric.MetricAggregationTemporalityCumulative) +} + +func (m *metricMysqlLockedConnects) 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 *metricMysqlLockedConnects) 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 *metricMysqlLockedConnects) emit(metrics pmetric.MetricSlice) { + if m.settings.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricMysqlLockedConnects(settings MetricSettings) metricMysqlLockedConnects { + m := metricMysqlLockedConnects{settings: settings} + if settings.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + type metricMysqlLocks struct { data pmetric.Metric // data buffer for generated metric. settings MetricSettings // metric settings provided by user. @@ -1873,6 +1928,7 @@ type MetricsBuilder struct { metricMysqlHandlers metricMysqlHandlers metricMysqlIndexIoWaitCount metricMysqlIndexIoWaitCount metricMysqlIndexIoWaitTime metricMysqlIndexIoWaitTime + metricMysqlLockedConnects metricMysqlLockedConnects metricMysqlLocks metricMysqlLocks metricMysqlLogOperations metricMysqlLogOperations metricMysqlOperations metricMysqlOperations @@ -1912,6 +1968,7 @@ func NewMetricsBuilder(settings MetricsSettings, buildInfo component.BuildInfo, metricMysqlHandlers: newMetricMysqlHandlers(settings.MysqlHandlers), metricMysqlIndexIoWaitCount: newMetricMysqlIndexIoWaitCount(settings.MysqlIndexIoWaitCount), metricMysqlIndexIoWaitTime: newMetricMysqlIndexIoWaitTime(settings.MysqlIndexIoWaitTime), + metricMysqlLockedConnects: newMetricMysqlLockedConnects(settings.MysqlLockedConnects), metricMysqlLocks: newMetricMysqlLocks(settings.MysqlLocks), metricMysqlLogOperations: newMetricMysqlLogOperations(settings.MysqlLogOperations), metricMysqlOperations: newMetricMysqlOperations(settings.MysqlOperations), @@ -1993,6 +2050,7 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { mb.metricMysqlHandlers.emit(ils.Metrics()) mb.metricMysqlIndexIoWaitCount.emit(ils.Metrics()) mb.metricMysqlIndexIoWaitTime.emit(ils.Metrics()) + mb.metricMysqlLockedConnects.emit(ils.Metrics()) mb.metricMysqlLocks.emit(ils.Metrics()) mb.metricMysqlLogOperations.emit(ils.Metrics()) mb.metricMysqlOperations.emit(ils.Metrics()) @@ -2113,6 +2171,16 @@ func (mb *MetricsBuilder) RecordMysqlIndexIoWaitTimeDataPoint(ts pcommon.Timesta mb.metricMysqlIndexIoWaitTime.recordDataPoint(mb.startTime, ts, val, ioWaitsOperationsAttributeValue.String(), tableNameAttributeValue, schemaAttributeValue, indexNameAttributeValue) } +// RecordMysqlLockedConnectsDataPoint adds a data point to mysql.locked_connects metric. +func (mb *MetricsBuilder) RecordMysqlLockedConnectsDataPoint(ts pcommon.Timestamp, inputVal string) error { + val, err := strconv.ParseInt(inputVal, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int64 for MysqlLockedConnects, value was %s: %w", inputVal, err) + } + mb.metricMysqlLockedConnects.recordDataPoint(mb.startTime, ts, val) + return nil +} + // RecordMysqlLocksDataPoint adds a data point to mysql.locks metric. func (mb *MetricsBuilder) RecordMysqlLocksDataPoint(ts pcommon.Timestamp, inputVal string, locksAttributeValue AttributeLocks) error { val, err := strconv.ParseInt(inputVal, 10, 64) diff --git a/receiver/mysqlreceiver/metadata.yaml b/receiver/mysqlreceiver/metadata.yaml index 8d919bdafd28..be320db787c3 100644 --- a/receiver/mysqlreceiver/metadata.yaml +++ b/receiver/mysqlreceiver/metadata.yaml @@ -283,6 +283,15 @@ metrics: monotonic: false aggregation: cumulative attributes: [threads] + mysql.locked_connects: + enabled: true + description: The number of attempts to connect to locked user accounts. + unit: 1 + sum: + value_type: int + input_type: string + monotonic: true + aggregation: cumulative mysql.tmp_resources: enabled: true description: The number of created temporary resources. diff --git a/receiver/mysqlreceiver/scraper.go b/receiver/mysqlreceiver/scraper.go index 9b7163505547..985ad4b1d33d 100644 --- a/receiver/mysqlreceiver/scraper.go +++ b/receiver/mysqlreceiver/scraper.go @@ -274,6 +274,10 @@ func (m *mySQLScraper) scrapeGlobalStats(now pcommon.Timestamp, errs *scrapererr case "Table_locks_waited": addPartialIfError(errs, m.mb.RecordMysqlLocksDataPoint(now, v, metadata.AttributeLocksWaited)) + // locked_connects + case "Locked_connects": + addPartialIfError(errs, m.mb.RecordMysqlLockedConnectsDataPoint(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 bed533c47f10..cbd541e5f401 100644 --- a/receiver/mysqlreceiver/testdata/scraper/expected.json +++ b/receiver/mysqlreceiver/testdata/scraper/expected.json @@ -1537,6 +1537,22 @@ }, "unit": "ns" }, + { + "description": "The number of attempts to connect to locked user accounts.", + "name": "mysql.locked_connects", + "sum": { + "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", + "dataPoints": [ + { + "asInt": "293", + "startTimeUnixNano": "1644862687825728000", + "timeUnixNano": "1644862687825772000" + } + ], + "isMonotonic": true + }, + "unit": "1" + }, { "description": "The number of created temporary resources.", "name": "mysql.tmp_resources",