From c49c252f8f05359b3f534776c20221e8cbef089c Mon Sep 17 00:00:00 2001 From: Rick Bradley Date: Tue, 12 Jul 2016 15:22:13 -0500 Subject: [PATCH] [QENG-4075] Allow specifying 'graphs:' for dashboard Prior to this the dashboard front-end would use the configuration settings for `graphite[:server]`/`graphite[:prefix]` to locate a graphite server to use for rendering graphs. Now that we have multiple possible metrics backends, the front-end graph host for the dashboard could be entirely different from the back-end metrics server that we publish to (if any). This decouples those settings: - use `graphs[:server]` / `graphs[:prefix]` for the graphite-compatible web front-end to use for dashboard display graphs - fall back to `graphite[:server]`/`graphite[:prefix]` if `graphs` is not specified, in order to support legacy `vmpooler.yaml` configurations. Note that since `statsd` takes precedence over `graphite`, it's possible to specify both `statsd` (for publishing) and `graphite` (for reading). We still prefer `graphs` over `graphite`. Updated the example `vmpooler.yaml` config file. --- lib/vmpooler/api/dashboard.rb | 72 ++++++++++++++++++++++++++--------- vmpooler.yaml.example | 26 +++++++++++++ 2 files changed, 79 insertions(+), 19 deletions(-) diff --git a/lib/vmpooler/api/dashboard.rb b/lib/vmpooler/api/dashboard.rb index b188dc5..3ef085a 100644 --- a/lib/vmpooler/api/dashboard.rb +++ b/lib/vmpooler/api/dashboard.rb @@ -1,9 +1,57 @@ module Vmpooler class API class Dashboard < Sinatra::Base + + # handle to the App's configuration information + def config + @config ||= Vmpooler::API.settings.config + end + + # configuration setting for server hosting graph URLs to view + def graph_server + return @graph_server if @graph_server + + if config[:graphs] + return false unless config[:graphs]['server'] + @graph_server = config[:graphs]['server'] + elsif config[:graphite] + return false unless config[:graphite]['server'] + @graph_server = config[:graphite]['server'] + else + false + end + end + + # configuration setting for URL prefix for graphs to view + def graph_prefix + return @graph_prefix if @graph_prefix + + if config[:graphs] + return false unless config[:graphs]['prefix'] + @graph_prefix = config[:graphs]['prefix'] + elsif config[:graphite] + return false unless config[:graphite]['prefix'] + @graph_prefix = config[:graphite]['prefix'] + else + false + end + end + + # what is the base URL for viewable graphs? + def graph_url + return false unless graph_server && graph_prefix + @graph_url ||= "http://#{graph_server}/render?target=#{graph_prefix}" + end + + # return a full URL to a viewable graph for a given metrics target (graphite syntax) + def graph_link(target = "") + return "" unless graph_url + graph_url + target + end + + get '/dashboard/stats/vmpooler/pool/?' do content_type :json - result = {} Vmpooler::API.settings.config[:pools].each do |pool| @@ -13,13 +61,11 @@ module Vmpooler end if params[:history] - if Vmpooler::API.settings.config[:graphite]['server'] + if graph_url history ||= {} begin - buffer = open( - 'http://' + Vmpooler::API.settings.config[:graphite]['server'] + '/render?target=' + Vmpooler::API.settings.config[:graphite]['prefix'] + '.ready.*&from=-1hour&format=json' - ).read + buffer = open(graph_link('.qready.*&from=-1hour&format=json')).read history = JSON.parse(buffer) history.each do |pool| @@ -52,59 +98,47 @@ module Vmpooler end end end - JSON.pretty_generate(result) end get '/dashboard/stats/vmpooler/running/?' do content_type :json - result = {} Vmpooler::API.settings.config[:pools].each do |pool| running = Vmpooler::API.settings.redis.scard('vmpooler__running__' + pool['name']) pool['major'] = Regexp.last_match[1] if pool['name'] =~ /^(\w+)\-/ - result[pool['major']] ||= {} - result[pool['major']]['running'] = result[pool['major']]['running'].to_i + running.to_i end if params[:history] - if Vmpooler::API.settings.config[:graphite]['server'] + if graph_url begin - buffer = open( - 'http://' + Vmpooler::API.settings.config[:graphite]['server'] + '/render?target=' + Vmpooler::API.settings.config[:graphite]['prefix'] + '.running.*&from=-1hour&format=json' - ).read + buffer = open(graph_link('.running.*&from=-1hour&format=json')).read JSON.parse(buffer).each do |pool| if pool['target'] =~ /.*\.(.*)$/ pool['name'] = Regexp.last_match[1] - pool['major'] = Regexp.last_match[1] if pool['name'] =~ /^(\w+)\-/ - result[pool['major']]['history'] ||= Array.new for i in 0..pool['datapoints'].length if pool['datapoints'][i] && pool['datapoints'][i][0] - pool['last'] = pool['datapoints'][i][0] - result[pool['major']]['history'][i] ||= 0 result[pool['major']]['history'][i] = result[pool['major']]['history'][i].to_i + pool['datapoints'][i][0].to_i else result[pool['major']]['history'][i] = result[pool['major']]['history'][i].to_i + pool['last'].to_i end end - end end rescue end end end - JSON.pretty_generate(result) end end diff --git a/vmpooler.yaml.example b/vmpooler.yaml.example index 64044e4..4e54891 100644 --- a/vmpooler.yaml.example +++ b/vmpooler.yaml.example @@ -54,6 +54,32 @@ server: 'redis.company.com' + # :graphs: + # + # This section contains the server and prefix information for a graphite- + # compatible web front-end where graphs may be viewed. This is used by the + # vmpooler dashboard to retrieve statistics and graphs for a given instance. + # + # NOTE: This is not the endpoint for publishing metrics data. See `graphite:` + # and `statsd:` below. + # + # NOTE: If `graphs:` is not set, for legacy compatibility, `graphite:` will be + # consulted for `server`/`prefix` information to use in locating a + # graph server for our dashboard. `graphs:` is recommended over + # `graphite:` + # + # + # Available configuration parameters: + # + # + # - server + # The FQDN hostname of the statsd daemon. + # (required) + # + # - prefix + # The prefix to use while storing statsd data. + # (optional; default: 'vmpooler') + # :statsd: # # This section contains the connection information required to store