-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Dynamic Metricsets (MySQL) #3170
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
//// | ||
This file is generated! See scripts/docs_collector.py | ||
//// | ||
|
||
[[metricbeat-metricset-mysql-query]] | ||
include::../../../module/mysql/query/_meta/docs.asciidoc[] | ||
|
||
|
||
==== Fields | ||
|
||
For a description of each field in the metricset, see the | ||
<<exported-fields-mysql,exported fields>> section. | ||
|
||
Here is an example document generated by this metricset: | ||
|
||
[source,json] | ||
---- | ||
include::../../../module/mysql/query/_meta/data.json[] | ||
---- |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"@timestamp":"2016-05-23T08:05:34.853Z", | ||
"beat":{ | ||
"hostname":"beathost", | ||
"name":"beathost" | ||
}, | ||
"metricset":{ | ||
"host":"localhost", | ||
"module":"mysql", | ||
"name":"status", | ||
"rtt":44269 | ||
}, | ||
"mysql":{ | ||
"query":{ | ||
"example": "query" | ||
} | ||
}, | ||
"type":"metricsets" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
=== mysql query MetricSet | ||
|
||
This is the query metricset of the module mysql. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
- name: query | ||
type: group | ||
description: > | ||
query | ||
fields: | ||
- name: example | ||
type: keyword | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not quite right, I think, because the resulting object is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, the PR is not complete yet and also not fully functional. Probably best would be to not ship a template in the first step at least. |
||
description: > | ||
Example field |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package query |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package query | ||
|
||
import ( | ||
"database/sql" | ||
|
||
"github.com/elastic/beats/libbeat/common" | ||
"github.com/elastic/beats/libbeat/logp" | ||
"github.com/elastic/beats/metricbeat/mb" | ||
"github.com/elastic/beats/metricbeat/module/mysql" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
var ( | ||
debugf = logp.MakeDebug("mysql-query") | ||
) | ||
|
||
func init() { | ||
if err := mb.Registry.AddMetricSet("mysql", "query", New, mysql.ParseDSN); err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
// MetricSet for fetching MySQL server query. | ||
type MetricSet struct { | ||
mb.BaseMetricSet | ||
db *sql.DB | ||
query string | ||
namespace string | ||
} | ||
|
||
// New creates and returns a new MetricSet instance. | ||
func New(base mb.BaseMetricSet) (mb.MetricSet, error) { | ||
|
||
// Unpack additional configuration options. | ||
config := struct { | ||
Query string `config:"query"` | ||
Namespace string `config:"namespace"` | ||
}{} | ||
err := base.Module().UnpackConfig(&config) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &MetricSet{ | ||
BaseMetricSet: base, | ||
query: config.Query, | ||
namespace: config.Namespace, | ||
}, nil | ||
} | ||
|
||
// Fetch fetches query messages from a mysql host. | ||
func (m *MetricSet) Fetch() (common.MapStr, error) { | ||
if m.db == nil { | ||
var err error | ||
m.db, err = mysql.NewDB(m.HostData().URI) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "mysql-query fetch failed") | ||
} | ||
} | ||
|
||
event, err := m.loadQuery(m.db, m.query) | ||
event["_metricsetName"] = m.namespace | ||
|
||
if err != nil { | ||
return event, err | ||
} | ||
|
||
return event, nil | ||
} | ||
|
||
// loadStatus loads all status entries from the given database into an array. | ||
func (m *MetricSet) loadQuery(db *sql.DB, query string) (common.MapStr, error) { | ||
// Returns all rows for the given query | ||
rows, err := db.Query(query) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer rows.Close() | ||
|
||
data := common.MapStr{} | ||
|
||
for rows.Next() { | ||
var name string | ||
var value string | ||
|
||
err = rows.Scan(&name, &value) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
data[name] = value | ||
} | ||
|
||
return data, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see we have a bit of a config issue here, as the
namespace
andquery
apply only to thequery
metricset but structurally the config seems to indicate they apply to the whole module. But that's a more general Metricbeat issue, right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is a more general problem we also have in other modules, for example ticks in the system module. To make it more obvious for the user we could namespace such configs with the metricset name, so it would be
query.query
which then probably needs a name change. Or for system, it would becpu.ticks: true
. Technically not really a difference, mainly a convention.