Skip to content
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

Support generic postgres custom metrics #224

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions manifests/integrations/mysql.pp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
# This class will install the necessary configuration for the mysql integration
#
# Parameters:
# $host:
# The host mysql is running on
# $password
# The mysql password for the datadog user
# $host:
# The host mysql is running on
# $user
# The mysql user for the datadog user
# $sock
Expand Down Expand Up @@ -37,8 +37,8 @@
#
#
class datadog_agent::integrations::mysql(
$host = 'localhost',
$password,
$host = 'localhost',
$user = 'datadog',
$sock = undef,
$tags = [],
Expand Down
6 changes: 3 additions & 3 deletions manifests/integrations/pgbouncer.pp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
# This class will install the necessary configuration for the pgbouncer integration
#
# Parameters:
# $password
# The password for the datadog user
# $host:
# The host pgbouncer is listening on
# $port
# The pgbouncer port number
# $username
# The username for the datadog user
# $password
# The password for the datadog user
# $tags
# Optional array of tags
#
Expand All @@ -25,10 +25,10 @@
#
#
class datadog_agent::integrations::pgbouncer(
$password,
$host = 'localhost',
$port = '6432',
$username = 'datadog',
$password,
$tags = [],
) inherits datadog_agent::params {

Expand Down
29 changes: 25 additions & 4 deletions manifests/integrations/postgres.pp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# This class will install the necessary configuration for the postgres integration
#
# Parameters:
# $password
# The password for the datadog user
# $host:
# The host postgres is running on
# $dbname
Expand All @@ -11,14 +13,18 @@
# The postgres port number
# $username
# The username for the datadog user
# $password
# The password for the datadog user
# $tags
# Optional array of tags
# $tables
# Track per relation/table metrics. Array of strings.
# Warning: this can collect lots of metrics per relation
# (10 + 10 per index)
# $tags
# Optional array of tags
# $custom_metrics
# A hash of custom metrics with the following keys - query, metrics,
# relation, descriptors. Refer to this guide for details on those fields:
# https://help.datadoghq.com/hc/en-us/articles/208385813-Postgres-custom-metric-collection-explained
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add an example with custom metrics below? Should help a bit with usability.

#
# Sample Usage:
#
Expand All @@ -27,17 +33,30 @@
# dbname => 'postgres'
# username => 'datadog',
# password => 'some_pass',
# custom_metrics => {
# a_custom_query => {
# query => "select tag_column, %s from table",
# relation => false,
# metrics => {
# value_column => ["value_column.datadog.tag", "GAUGE"]
# },
# descriptors => [
# ["tag_column", "tag_column.datadog.tag"]
# ]
# }
# }
# }
#
#
class datadog_agent::integrations::postgres(
$password,
$host = 'localhost',
$dbname = 'postgres',
$port = '5432',
$username = 'datadog',
$password,
$tags = [],
$tables = []
$tables = [],
$custom_metrics = {},
) inherits datadog_agent::params {
include datadog_agent

Expand All @@ -53,4 +72,6 @@
require => Package[$datadog_agent::params::package_name],
notify => Service[$datadog_agent::params::service_name],
}

create_resources('datadog_agent::integrations::postgres_custom_metric', $custom_metrics)
}
27 changes: 27 additions & 0 deletions manifests/integrations/postgres_custom_metric.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
##
# The postgres_custom_metric defines a custom sql metric.
# https://help.datadoghq.com/hc/en-us/articles/208385813-Postgres-custom-metric-collection-explained
#
# $query:
# The custom metric SQL query. It must contain a '%s' for defining the metrics.
#
# $metrics:
# a hash of column name to metric definition. a metric definition is an array
# consisting of two columns -- the datadog metric name and the metric type.
#
# $relation:
# ?
#
# $descriptor:
# an array that maps an sql column's to a tag. Each descriptor consists of two
# fields -- column name, and datadog tag.
define datadog_agent::integrations::postgres_custom_metric(
$query,
$metrics,
$relation = false,
$descriptors = [],
) {
validate_re($query, '^.*%s.*$', 'custom_metrics require %s for metric substitution')
validate_hash($metrics)
validate_array($descriptors)
}
47 changes: 47 additions & 0 deletions spec/classes/datadog_agent_integrations_postgres_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,53 @@
it { should contain_file(conf_file).with_content(%r{username: monitoring}) }
it { should contain_file(conf_file).with_content(%r{^[^#]*tags:\s+- foo\s+- bar\s+- baz}) }
it { should contain_file(conf_file).with_content(%r{^[^#]*relations:\s+- furry\s+- fuzzy\s+- funky}) }

context 'with custom metric query missing %s' do
let(:params) {{
host: 'postgres1',
dbname: 'cats',
port: 4142,
username: 'monitoring',
password: 'abc123',
custom_metrics: {
'query_is_missing_%s' => {
'query' => 'select * from fuzz',
'metrics' => { },
}
}
}}
it do
expect {
is_expected.to compile
}.to raise_error(/custom_metrics require %s for metric substitution/)
end
end

context 'with custom metric query' do
let(:params) {{
host: 'postgres1',
dbname: 'cats',
port: 4142,
username: 'monitoring',
password: 'abc123',
custom_metrics: {
'foo_gooo_bar_query' => {
'query' => 'select foo, %s from bar',
'metrics' => {
"gooo" => ["custom_metric.tag.gooo", "GAUGE"]
},
'descriptors' => [["foo", "custom_metric.tag.foo"]]
}
}
}}
it { is_expected.to compile }
it { should contain_file(conf_file).with_content(%r{^[^#]*custom_metrics:}) }
it { should contain_file(conf_file).with_content(%r{\s+query:\s*['"]?select foo, %s from bar['"]?}) }
it { should contain_file(conf_file).with_content(%r{\s+metrics:}) }
it { should contain_file(conf_file).with_content(%r{\s+"gooo":\s+\[custom_metric.tag.gooo, GAUGE\]}) }
it { should contain_file(conf_file).with_content(%r{\s+query.*\n\s+relation:\s*false}) }
it { should contain_file(conf_file).with_content(%r{\s+descriptors.*\n\s+-\s+\[foo, custom_metric.tag.foo\]}) }
end
end
end

Expand Down
31 changes: 31 additions & 0 deletions templates/agent-conf.d/postgres.yaml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,34 @@ instances:
<%- end -%>
<%- end -%>
<% end -%>
# https://help.datadoghq.com/hc/en-us/articles/208385813-Postgres-custom-metric-collection-explained
# custom_metrics:
# - # Capture simple data
# query: SELECT name, address, %s from company where name = 'Paul'; # this query will be run and "%s" replaced with the parameters defined in the metrics section just below
# metrics:
# age: [postgresql.employee_age, GAUGE] # the value contained in column "age" will be captured and submitted as a gauge metric named "postgresql.employee.age"
# salary: [postgresql.employee_salary, GAUGE]
# relation: false # when relation is not an empty list, it gathers per-relation metrics on top of that.
# descriptors:
# - [name, name] # captures the content of the "name" column as a tag for the 2 metrics defined
# - [address, localisation] # captures the content of "address" column as a tag and renames this tag "localisation"
#
<% if @custom_metrics and ! @custom_metrics.empty? -%>
custom_metrics:
<%- Array(@custom_metrics).each do |n, custom_metric| -%>
- query: <%= custom_metric["query"] %>
relation: <%= custom_metric["relation"]? "true" : "false" %>
metrics:
<%- Array(custom_metric["metrics"]).each do |metric_name, metric_descriptor| -%>
"<%= metric_name %>": [<%= metric_descriptor[0] %>, <%= metric_descriptor[1] %>]
<%- end -%>
<%- if custom_metric["descriptors"] == nil || custom_metric["descriptors"].empty? -%>
descriptors: []
<%- else -%>
descriptors:
<%- Array(custom_metric["descriptors"]).each do |descriptor| -%>
- [<%=descriptor[0]%>, <%=descriptor[1] %>]
<%- end -%>
<%- end -%>
<%- end -%>
<% end -%>