12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# Minor Release 4.1.0

## Improvements
- Retrieve all additional metrics with one POST instead of multiple GETs
- [PR #23](https://github.com/npwalker/pe_metric_curl_cron_jobs/pull/23)
- Add a `--print` command line argument to the metrics scripts
- This allows for integrations with other tools that can read the output from stdout.
- [PR #24](https://github.com/npwalker/pe_metric_curl_cron_jobs/pull/24)
- Move script configuration into a YAML file
- Allow the metrics scripts to be stored as static files instead of templates
- [PR #25](https://github.com/npwalker/pe_metric_curl_cron_jobs/pull/25)

# Major Release 4.0.0

This is a major release because some of the PuppetDB metrics are renamed.
Expand Down
87 changes: 31 additions & 56 deletions templates/activemq_metrics.epp → files/amq_metrics
Original file line number Diff line number Diff line change
@@ -1,65 +1,35 @@
<%- | String $output_dir,
Array[String] $hosts,
String $metrics_type,
Integer $metrics_port,
Array[Hash] $additional_metrics,
| -%>
#!/opt/puppetlabs/puppet/bin/ruby

require "net/https"
require "json"
require "uri"
require 'time'
require 'optparse'
require 'yaml'

OUTPUT_DIR = "<%= $output_dir %>"
METRICS_TYPE = "<%= $metrics_type %>"

HOSTS = [
<% $hosts.each |$host| { -%>
"<%= $host %>",
<% } -%>
]
PORT = "<%= $metrics_port %>"

POST_DATA = '
[
{
"type": "read",
"mbean": "java.lang:type=Memory",
"attribute": "HeapMemoryUsage,NonHeapMemoryUsage"
},
{
"type": "read",
"mbean": "java.lang:name=*,type=GarbageCollector",
"attribute": "CollectionCount"
},
{
"type": "read",
"mbean": "java.lang:type=Runtime",
"attribute": "Uptime"
},
{
"type": "read",
"mbean": "java.lang:type=OperatingSystem",
"attribute": "OpenFileDescriptorCount,MaxFileDescriptorCount"
},
{
"type": "read",
"mbean": "org.apache.activemq:brokerName=*,type=Broker",
"attribute": "MemoryLimit,MemoryPercentUsage,CurrentConnectionsCount"
},
{
"type": "read",
"mbean": "org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=mcollective.*",
"attribute": "AverageBlockedTime,AverageEnqueueTime,AverageMessageSize,ConsumerCount,DequeueCount,DispatchCount,EnqueueCount,ExpiredCount,ForwardCount,InFlightCount,ProducerCount,QueueSize",
},
{
"type": "read",
"mbean": "org.apache.activemq:type=Broker,brokerName=*,destinationType=Topic,destinationName=mcollective.*.agent",
"attribute": "AverageBlockedTime,AverageEnqueueTime,AverageMessageSize,ConsumerCount,DequeueCount,DispatchCount,EnqueueCount,ExpiredCount,ForwardCount,InFlightCount,ProducerCount,QueueSize",
},
]
'
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: tk_metrics [options]"

opts.on('-p', '--print', 'Print to stdout') { |v| options[:print] = true }
opts.on('-m [TYPE]', '--metrics_type [TYPE]', 'Type of metric to collect') { |v| options[:metrics_type] = v }
end.parse!

if options[:metrics_type].nil? then
STDERR.puts '--metrics_type (-m) is a required argument'
exit 1
end

METRICS_TYPE = options[:metrics_type]
config = YAML.load_file(File.join(File.dirname(File.expand_path(__FILE__)),"#{METRICS_TYPE}_config.yaml"))

OUTPUT_DIR = config['output_dir']
HOSTS = config['hosts']
PORT = config['metrics_port']
METRICS = config['additional_metrics']
CLIENTCERT = config['clientcert']

POST_DATA = METRICS.to_json

def recurse_merge!(a,b)
a.merge!(b) do |_,aa,bb|
Expand Down Expand Up @@ -127,12 +97,17 @@ HOSTS.each do |host|
dataset['servers'][hostkey][METRICS_TYPE]['api-query-start'] = timestamp.utc.iso8601
dataset['servers'][hostkey][METRICS_TYPE]['api-query-duration'] = Time.now - timestamp

json_dataset = JSON.pretty_generate(dataset)

Dir.chdir(OUTPUT_DIR) do
Dir.mkdir(host) unless File.exist?(host)
File.open(File.join(host, filename), 'w') do |file|
file.write(JSON.pretty_generate(dataset))
file.write(json_dataset)
end
end
if options[:print] == true then
STDOUT.write(json_dataset)
end
rescue Exception => e
STDERR.puts "Error getting metrics for #{host}: #{e}"
end
Expand Down
116 changes: 116 additions & 0 deletions files/tk_metrics
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/opt/puppetlabs/puppet/bin/ruby

require "net/https"
require "json"
require "uri"
require 'time'
require 'optparse'
require 'yaml'

options = {}
OptionParser.new do |opts|
opts.banner = "Usage: tk_metrics [options]"

opts.on('-p', '--print', 'Print to stdout') { |v| options[:print] = true }
opts.on('-m [TYPE]', '--metrics_type [TYPE]', 'Type of metric to collect') { |v| options[:metrics_type] = v }
end.parse!

if options[:metrics_type].nil? then
STDERR.puts '--metrics_type (-m) is a required argument'
exit 1
end

METRICS_TYPE = options[:metrics_type]
config = YAML.load_file(File.join(File.dirname(File.expand_path(__FILE__)),"#{METRICS_TYPE}_config.yaml"))

OUTPUT_DIR = config['output_dir']
HOSTS = config['hosts']
PORT = config['metrics_port']
METRICS = config['additional_metrics']
CLIENTCERT = config['clientcert']

$error_array = []

def get_endpoint(url)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.cert = OpenSSL::X509::Certificate.new(File.read("/etc/puppetlabs/puppet/ssl/certs/#{CLIENTCERT}.pem"))
http.key = OpenSSL::PKey::RSA.new(File.read("/etc/puppetlabs/puppet/ssl/private_keys/#{CLIENTCERT}.pem"))
http.ca_file = '/etc/puppetlabs/puppet/ssl/certs/ca.pem'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
data = JSON.parse(http.get(uri.request_uri).body)
rescue Exception => e
$error_array << "#{e}"
data = {}
end

def post_endpoint(url,post_data)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.cert = OpenSSL::X509::Certificate.new(File.read("/etc/puppetlabs/puppet/ssl/certs/#{CLIENTCERT}.pem"))
http.key = OpenSSL::PKey::RSA.new(File.read("/etc/puppetlabs/puppet/ssl/private_keys/#{CLIENTCERT}.pem"))
http.ca_file = '/etc/puppetlabs/puppet/ssl/certs/ca.pem'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Post.new(uri.request_uri)
request.content_type = 'application/json'
request.body = post_data

data = JSON.parse(http.request(request).body)
rescue Exception => e
$error_array << "#{e}"
data = {}
end

filename = Time.now.utc.strftime('%Y%m%dT%H%M%SZ') + '.json'

HOSTS.each do |host|
begin
timestamp = Time.now
dataset = {'timestamp' => timestamp.utc.iso8601, 'servers' => {}}
hostkey = host.gsub('.', '-')

host_url = "https://#{host}:#{PORT}"

status_endpoint = "#{host_url}/status/v1/services?level=debug"
status_output = get_endpoint(status_endpoint)
dataset['servers'][hostkey] = {METRICS_TYPE => status_output}

post_data = []

unless METRICS.empty? then
METRICS.each do |metric|
post_data << metric['url']
end

endpoint = "#{host_url}/metrics/v1/mbeans"
metrics_output = post_endpoint(endpoint, post_data.to_json)

METRICS.each_index do |index|
metric_name = METRICS[index]['name']
metric_data = metrics_output[index]

dataset['servers'][hostkey][METRICS_TYPE][metric_name] = metric_data
end
end

dataset['servers'][hostkey][METRICS_TYPE]['error'] = $error_array
dataset['servers'][hostkey][METRICS_TYPE]['error_count'] = $error_array.count
dataset['servers'][hostkey][METRICS_TYPE]['api-query-start'] = timestamp.utc.iso8601
dataset['servers'][hostkey][METRICS_TYPE]['api-query-duration'] = Time.now - timestamp

json_dataset = JSON.pretty_generate(dataset)

Dir.chdir(OUTPUT_DIR) do
Dir.mkdir(host) unless File.exist?(host)
File.open(File.join(host, filename), 'w') do |file|
file.write(json_dataset)
end
end
if options[:print] == true then
STDOUT.write(json_dataset)
end
end
end
14 changes: 14 additions & 0 deletions lib/puppet/functions/pe_metric_curl_cron_jobs/to_yaml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'yaml'

Puppet::Functions.create_function(:'pe_metric_curl_cron_jobs::to_yaml') do
dispatch :to_yaml do
param 'Hash', :hash_or_array
end
dispatch :to_yaml do
param 'Array', :hash_or_array
end

def to_yaml(hash_or_array)
hash_or_array.to_yaml
end
end
51 changes: 49 additions & 2 deletions manifests/activemq.pp
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,64 @@
Array[String] $hosts = $::pe_metric_curl_cron_jobs::activemq_hosts,
Integer $port = $::pe_metric_curl_cron_jobs::activemq_port,
) {
$scripts_dir = $::pe_metric_curl_cron_jobs::scripts_dir

Pe_metric_curl_cron_jobs::Pe_metric {
output_dir => $::pe_metric_curl_cron_jobs::output_dir,
scripts_dir => $::pe_metric_curl_cron_jobs::scripts_dir,
scripts_dir => $scripts_dir,
cron_minute => "*/${collection_frequency}",
retention_days => $retention_days,
}

$additional_metrics = [
{
'type' => 'read',
'mbean' => 'java.lang:type=Memory',
'attribute' => 'HeapMemoryUsage,NonHeapMemoryUsage'
},
{
'type' => 'read',
'mbean' => 'java.lang:name=*,type=GarbageCollector',
'attribute' => 'CollectionCount'
},
{
'type' => 'read',
'mbean' => 'java.lang:type=Runtime',
'attribute' => 'Uptime'
},
{
'type' => 'read',
'mbean' => 'java.lang:type=OperatingSystem',
'attribute' => 'OpenFileDescriptorCount,MaxFileDescriptorCount'
},
{
'type' => 'read',
'mbean' => 'org.apache.activemq:brokerName=*,type=Broker',
'attribute' => 'MemoryLimit,MemoryPercentUsage,CurrentConnectionsCount'
},
{
'type' => 'read',
'mbean' => 'org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=mcollective.*',
'attribute' => 'AverageBlockedTime,AverageEnqueueTime,AverageMessageSize,ConsumerCount,DequeueCount,DispatchCount,EnqueueCount,ExpiredCount,ForwardCount,InFlightCount,ProducerCount,QueueSize',
},
{
'type' => 'read',
'mbean' => 'org.apache.activemq:type=Broker,brokerName=*,destinationType=Topic,destinationName=mcollective.*.agent',
'attribute' => 'AverageBlockedTime,AverageEnqueueTime,AverageMessageSize,ConsumerCount,DequeueCount,DispatchCount,EnqueueCount,ExpiredCount,ForwardCount,InFlightCount,ProducerCount,QueueSize',
},
]

file { "${scripts_dir}/amq_metrics" :
ensure => present,
mode => '0744',
source => 'puppet:///modules/pe_metric_curl_cron_jobs/amq_metrics',
}

pe_metric_curl_cron_jobs::pe_metric { 'activemq' :
metric_ensure => $metrics_ensure,
hosts => $hosts,
metrics_port => $port,
metric_script_template => 'activemq_metrics.epp',
metric_script_file => 'amq_metrics',
additional_metrics => $additional_metrics,
}
}
6 changes: 6 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
ensure => directory,
}

file { "${scripts_dir}/tk_metrics" :
ensure => present,
mode => '0744',
source => 'puppet:///modules/pe_metric_curl_cron_jobs/tk_metrics'
}

include pe_metric_curl_cron_jobs::puppetserver

include pe_metric_curl_cron_jobs::puppetdb
Expand Down
Loading