wavefront-client 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YTkyYWUzNzQ3MTVmYjhlNGI3NWZlZDM5YTBjYTAwMzNkMTQ2MjQ0YQ==
4
+ MjE5OWM5OWIyYjcxNWI2MGJjNGRiOWI1YjBlMjI1OWFiMzIyMWVjYg==
5
5
  data.tar.gz: !binary |-
6
- NDNlN2ZiNmYxNDE0NzhlMzdjMTJhNjExZGI4ZjhhY2Q0YWE5YjViMw==
6
+ OGJkZTg1ZTgwMDdjMmZhZDhiYjIyZDVlYmJlYzMzNGZiZDI4ZWEyOQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YzQxYzE3NGZmNzkwNWRjYzgxYWM0MDBhNDk5OGM1NGZlMjE4MDA2ZWI2YTNi
10
- YTRhNTQxYTIzYzFhNWRlYTgxYzIyNWI1OTgwNTA1ZWE0NjFmMjY0M2Y2ODg3
11
- ZmVlOTJmZDk2YTdiYjVkOGEzOTUzYTMwYjk3NTU5NjVkOWRjZjI=
9
+ YTBhNmI4OWJmOWJlM2I2NDMwYTNhNjIzMGNjZjM0OWVlMjdjMzU1YWUwNjYy
10
+ MTZjYjIwYjI2MDhlNDU3ZmJjYmZjODk1NmY0ZTM0OGJlMzMzMDJjZmNjN2Jk
11
+ MDk4N2MxODQzYzQ0MDQxMzRkY2Y2YzMwOWE3ODA3ZGFjZDA2MGM=
12
12
  data.tar.gz: !binary |-
13
- MDljMjNlYzg3YTJhNjY0YWQ3MDA0Y2M2ZDYyOWVjMzlkOTA5NzEyMjJhMzNl
14
- NmFhMjVmMjI4MDAyNjEzNTc1OTlmOWE5ZWYyY2Y4MzY2ZDg5ODAzOTI2OGEw
15
- ZTg0NWFiZGQyOTNhZGRkYmEyNmE3ZGNiMzI2NmIxYjBmNjY1NmE=
13
+ YjJhOGNmOTEyYzE1ZmRlN2JhMjNkMTgwMmVmOGU2YWJhYjY2MGRjMGVmNTFm
14
+ YjQwZmJhMTRhYTBhYWRmM2ViNGIyZjlhYTQ5Y2JiYzIxOTMyZTQyZDUxNTdl
15
+ MGNlMWVhMjNlNjkzM2U2MjAwNjdmY2QxYzgyOWExZGQyYTc2ZDE=
data/README.md CHANGED
@@ -180,16 +180,18 @@ See `<command> --help` for more information on a specific command.
180
180
 
181
181
  $ wavefront ts --help
182
182
  Usage: wavefront COMMAND QUERY (OPTIONS)
183
- -d, --days Query granularity of days
183
+ -c, --config path to configuration file (default: ${HOME}/.wavefront)
184
+ -P, --profile profile in configuration file (default: default)
184
185
  -D, --debug Enable debug mode
186
+ -S, --seconds Query granularity of seconds
185
187
  -m, --minutes Query granularity of minutes
186
188
  -H, --hours Query granularity of hours
187
- -E, --endpoint Connect to alternative cluster endpoint (default: metrics.wavefront.com)
188
- -S, --seconds Query granularity of seconds
189
- -s, --start Time in UNIX epoch seconds to begin the query from
189
+ -d, --days Query granularity of days
190
+ -s, --start start of query window in epoch seconds or parseable format
191
+ -e, --end end of query window in epoch seconds or parseable format
190
192
  -t, --token Wavefront authentication token
191
- -e, --end Time in UNIX epoch seconds to query to
192
- -f, --format Output format (raw, ruby, graphite, highcharts) (default: raw)
193
+ -E, --endpoint Connect to alternative cluster endpoint (default: metrics.wavefront.com)
194
+ -f, --format Output format (raw, ruby, graphite, highcharts, human) (default: raw)
193
195
  -p, --prefixlength The number of path elements to treat as a prefix when doing schema manipulations (default: 1)
194
196
  -X, --strict Flag to not return points outside the query window [q;s) (default: true)
195
197
  -O, --includeObsoleteMetrics Flag to include metrics that have not been reporting for more than 4 weeks,defaults to false
@@ -213,6 +215,55 @@ $ wavefront alerts snoozed -t TOKEN -f json --shared ops
213
215
  ...
214
216
  ```
215
217
 
218
+ #### Notes on Options
219
+
220
+ ##### Times
221
+
222
+ The query window can be defined by using Unix epoch times (as shown
223
+ by `date "%+s"`) or by entering any Ruby `strptime`-parseable string.
224
+ For instance:
225
+
226
+ ```bash
227
+ $ wavefront --start 12:15 --end 12:20 ...
228
+ ```
229
+
230
+ will request data points between 12:15 and 12:20pm today. If you ran
231
+ that in the morning, the time would be invalid, and you would get a
232
+ 400 error from Wavefront, so something of the form
233
+ `2016-04-17T12:25:00` would remove all ambiguity.
234
+
235
+ There is no need to include a timezone in your parseable string: the
236
+ `wavefront` CLI will automatically use your local timezone when it
237
+ parses the string.
238
+
239
+ #### Default Configuration
240
+
241
+ Passing tokens and endpoints into the `wavefront` command can become
242
+ tiresome, so you can put such data into an `ini`-style configuration
243
+ file. By default this file should be located at `${HOME}/.wavefront`,
244
+ though you can override the location with the `-c` flag.
245
+
246
+ You can switch between Wavefront accounts using profile stanzas,
247
+ selected with the `-P` option. If `-P` is not supplied, the
248
+ `default` profile will be used. Not having a useable configuration
249
+ file will not cause an error.
250
+
251
+ A configuration file looks like this:
252
+
253
+ ```
254
+ [default]
255
+ token = abcdefab-1234-abcd-1234-abcdefabcdef
256
+ endpoint = companya.wavefront.com
257
+ format = human
258
+
259
+ [companyb]
260
+ token = 12345678-abcd-0123-abcd-123456789abc
261
+ endpoint = metrics.wavefront.com
262
+ ```
263
+
264
+ The key for each key-value pair can match any long option show in the
265
+ command `help`, so you can set, for instance, a default output
266
+ format, as shown above.
216
267
 
217
268
  ## Building and installing
218
269
 
data/bin/wavefront CHANGED
@@ -12,52 +12,94 @@
12
12
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
-
15
+ #
16
16
  require 'wavefront/client'
17
17
  require 'slop'
18
+ require 'pathname'
19
+ require 'wavefront/cli'
18
20
 
21
+ begin
19
22
  options = Slop.parse(strict: true) do
20
23
  banner 'Usage: wavefront COMMAND QUERY (OPTIONS)'
21
24
  on 'h', 'help', 'Display this message'
22
25
 
26
+ command :version do
27
+ description 'Display the client version and exit'
28
+ run do
29
+ puts Wavefront::Client::VERSION
30
+ exit 0
31
+ end
32
+ end
33
+
23
34
  command 'ts' do
24
35
  description "Query the timeseries"
25
- on 'd', 'days', 'Query granularity of days'
36
+ on 'c', 'config=', 'path to configuration file', default:
37
+ Pathname.new(ENV['HOME']) + '.wavefront'
38
+ on 'P', 'profile=', 'profile in configuration file', default: 'default'
26
39
  on 'D', 'debug', 'Enable debug mode'
40
+ on 'S', 'seconds', 'Query granularity of seconds'
27
41
  on 'm', 'minutes', 'Query granularity of minutes'
28
42
  on 'H', 'hours', 'Query granularity of hours'
29
- on 'E', 'endpoint=', 'Connect to alternative cluster endpoint', default: Wavefront::Client::DEFAULT_HOST.to_s
30
- on 'S', 'seconds', 'Query granularity of seconds'
31
- on 's', 'start=', 'Time in UNIX epoch seconds to begin the query from'
43
+ on 'd', 'days', 'Query granularity of days'
44
+ on 's', 'start=', 'start of query window in epoch seconds or parseable format'
45
+ on 'e', 'end=', 'end of query window in epoch seconds or parseable format'
32
46
  on 't', 'token=', 'Wavefront authentication token'
33
- on 'e', 'end=', 'Time in UNIX epoch seconds to query to'
47
+ on 'E', 'endpoint=', 'Connect to alternative cluster endpoint', default: Wavefront::Client::DEFAULT_HOST.to_s
34
48
  on 'f', 'format=', "Output format (#{Wavefront::Client::FORMATS.join(', ')})", default: Wavefront::Client::DEFAULT_FORMAT.to_s
35
- on 'p', 'prefixlength=', 'The number of path elements to treat as a prefix when doing schema manipulations', default: Wavefront::Client::DEFAULT_PREFIX_LENGTH
49
+ on 'p', 'prefixlength=', 'Number of path elements to treat as a prefix in schema manipulation', default: Wavefront::Client::DEFAULT_PREFIX_LENGTH
36
50
  on 'X', 'strict=','Flag to not return points outside the query window [q;s) ', default: Wavefront::Client::DEFAULT_STRICT
37
- on 'O', 'includeObsoleteMetrics=', 'Flag to include metrics that have not been reporting for more than 4 weeks,defaults to false', default: Wavefront::Client::DEFAULT_OBSOLETE_METRICS
51
+ on 'O', 'includeObsoleteMetrics=', 'Include metrics which have not reported for > 4 weeks', default: Wavefront::Client::DEFAULT_OBSOLETE_METRICS
38
52
  on 'h', 'help', 'Display this message'
39
53
  run do |options, arguments|
54
+ pf_opts = Wavefront::Cli.new(options, arguments).load_profile || {}
40
55
  require 'wavefront/cli/ts'
41
- cli = Wavefront::Cli::Ts.new(options, arguments)
42
- cli.run
56
+ cli = Wavefront::Cli::Ts.new(options.to_hash.merge(pf_opts), arguments)
57
+ begin
58
+ cli.run
59
+ rescue => e
60
+ puts 'Timeseries query failed.'
61
+ puts e
62
+ exit 1
63
+ end
43
64
  end
44
65
  end
45
66
 
46
67
  command 'alerts' do
68
+ banner 'Usage: wavefront alerts (OPTIONS) ALERT_STATE'
47
69
  description "Query alerts"
70
+ on 'c', 'config=', 'path to configuration file', default:
71
+ Pathname.new(ENV['HOME']) + '.wavefront'
72
+ on 'P', 'profile=', 'profile in configuration file', default: 'default'
48
73
  on 'E', 'endpoint=', 'Connect to alternative cluster endpoint', default: Wavefront::Client::DEFAULT_HOST.to_s
49
74
  on 'f', 'format=', 'Output format (ruby, json)', default: 'ruby'
75
+ on 'f', 'format=', "Output format (#{Wavefront::Client::ALERT_FORMATS.join(', ')})", default: Wavefront::Client::DEFAULT_ALERT_FORMAT.to_s
50
76
  on 'h', 'help', 'Display this message'
51
77
  on 'p', 'private=', 'Retrieve only alerts with named private tags, comma delimited.'
52
78
  on 's', 'shared=', 'Retrieve only alerts with named shared tags, comma delimited.'
53
79
  on 't', 'token=', 'Wavefront authentication token'
54
80
  run do |options, arguments|
81
+ pf_opts = Wavefront::Cli.new(options, arguments).load_profile || {}
55
82
  require 'wavefront/cli/alerts'
56
- cli = Wavefront::Cli::Alerts.new(options, arguments)
57
- cli.run
83
+ cli = Wavefront::Cli::Alerts.new(options.to_hash.merge(pf_opts),
84
+ arguments)
85
+ begin
86
+ cli.run
87
+ rescue => e
88
+ puts 'Alert query failed.'
89
+ puts e
90
+ exit 1
91
+ end
58
92
  end
59
93
  end
60
94
 
95
+
96
+ end
97
+ rescue Slop::InvalidOptionError => e
98
+ puts 'invalid option error: '+ e.to_s
99
+ exit 1
100
+ rescue Slop::MissingArgumentError => e
101
+ puts 'option parsing error: '+ e.to_s
102
+ exit 1
61
103
  end
62
104
 
63
105
  puts options
@@ -17,6 +17,7 @@ require 'wavefront/alerting'
17
17
  require 'wavefront/cli'
18
18
  require 'json'
19
19
  require 'pp'
20
+ require 'time'
20
21
 
21
22
  class Wavefront::Cli::Alerts < Wavefront::Cli
22
23
 
@@ -26,12 +27,18 @@ class Wavefront::Cli::Alerts < Wavefront::Cli
26
27
  alerts = Wavefront::Alerting.new(@options[:token])
27
28
  queries = alerts.public_methods(false).sort
28
29
  queries.delete(:token)
29
-
30
- if arguments[0]
31
- query = arguments[0].to_sym
32
- else
33
- puts "Your query should be one of: #{ queries.each {|q| q.to_s}.join(', ') }. See --help for more information"
34
- exit 1
30
+
31
+ raise 'Missing query.' if arguments.empty?
32
+ query = arguments[0].to_sym
33
+
34
+ unless queries.include?(query)
35
+ raise 'State must be one of: ' + queries.each {|q| q.to_s}.join(', ')
36
+ end
37
+
38
+ unless Wavefront::Client::ALERT_FORMATS.include?(
39
+ @options[:format].to_sym)
40
+ raise 'Output format must be one of: ' +
41
+ Wavefront::Client::ALERT_FORMATS.join(', ')
35
42
  end
36
43
 
37
44
  # This isn't especially nice, but if require to
@@ -42,22 +49,20 @@ class Wavefront::Cli::Alerts < Wavefront::Cli
42
49
  if @options[:shared]
43
50
  options[:shared_tags] = @options[:shared].delete(' ').split(',')
44
51
  end
52
+
45
53
  if @options[:private]
46
54
  options[:private_tags] = @options[:private].delete(' ').split(',')
47
55
  end
48
56
 
49
- if queries.include?(query)
50
- result = alerts.send(query, options)
51
- else
52
- puts "Your query should be one of: #{ queries.each {|q| q.to_s}.join(', ') }. See --help for more information"
53
- exit 1
54
- end
57
+ result = alerts.send(query, options)
55
58
 
56
59
  case @options[:format].to_sym
57
60
  when :ruby
58
61
  pp result
59
62
  when :json
60
63
  puts JSON.pretty_generate(JSON.parse(result))
64
+ when :human
65
+ puts humanize(JSON.parse(result))
61
66
  else
62
67
  puts "Invalid output format, See --help for more detail."
63
68
  exit 1
@@ -65,4 +70,79 @@ class Wavefront::Cli::Alerts < Wavefront::Cli
65
70
 
66
71
  exit 0
67
72
  end
73
+
74
+ def humanize(alerts)
75
+ #
76
+ # Selectively display alert information in an easily
77
+ # human-readable format. I have chosen not to display certain
78
+ # fields which I don't think are useful in this context. I also
79
+ # wish to put the fields in order. Here are the fields I want, in
80
+ # the order I want them.
81
+ #
82
+ row_order = %w(name created severity condition displayExpression
83
+ minutes resolveAfterMinutes updated alertStates
84
+ metricsUsed hostsUsed additionalInformation)
85
+
86
+ # build up an array of lines then turn it into a string and
87
+ # return it
88
+ #
89
+ # Most things get printed with the human_line() method, but some
90
+ # data needs special handling. To do that, just add a method
91
+ # called human_line_key() where key is something in row_order,
92
+ # and it will be found.
93
+ #
94
+ x = alerts.map do |alert|
95
+ row_order.map do |key|
96
+ lm = "human_line_#{key}"
97
+ if self.respond_to?(lm)
98
+ self.method(lm.to_sym).call(key, alert[key])
99
+ else
100
+ human_line(key, alert[key])
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ def human_line(k, v)
107
+ '%-22s%s' % [k, v]
108
+ end
109
+
110
+ def human_line_created(k, v)
111
+ #
112
+ # The 'created' and 'updated' timestamps are in epoch
113
+ # milliseconds
114
+ #
115
+ human_line(k, Time.at(v / 1000))
116
+ end
117
+
118
+ def human_line_updated(k, v)
119
+ human_line_created(k, v)
120
+ end
121
+
122
+ def human_line_hostsUsed(k, v)
123
+ #
124
+ # Put each host on its own line, indented.
125
+ #
126
+ v.sort!
127
+ [human_line(k, v.shift)] + v.map {|el| human_line('', el)}
128
+ end
129
+
130
+ def human_line_metricsUsed(k, v)
131
+ human_line_hostsUsed(k, v)
132
+ end
133
+
134
+ def human_line_alertStates(k, v)
135
+ human_line(k, v.join(','))
136
+ end
137
+
138
+ def human_line_additionalInformation(k, v)
139
+ human_line(k, indent_wrap(v))
140
+ end
141
+
142
+ def indent_wrap(line, cols=78, offset=22)
143
+ #
144
+ # hanging indent long lines to fit in an 80-column terminal
145
+ #
146
+ line.gsub(/(.{1,#{cols - offset}})(\s+|\Z)/, "\\1\n#{' ' * offset}")
147
+ end
68
148
  end
@@ -17,29 +17,39 @@ require 'wavefront/client'
17
17
  require 'wavefront/cli'
18
18
  require 'pp'
19
19
  require 'json'
20
+ require 'date'
20
21
 
21
22
  class Wavefront::Cli::Ts < Wavefront::Cli
22
23
 
23
24
  attr_accessor :options, :arguments
24
25
 
26
+ def parse_time(t)
27
+ return Time.at(t.to_i) if t.match(/^\d+$/)
28
+ begin
29
+ return DateTime.parse("#{t} #{Time.now.getlocal.zone}").to_time.utc
30
+ rescue
31
+ raise "cannot parse timestamp '#{t}'."
32
+ end
33
+ end
34
+
25
35
  def run
36
+ raise 'Please supply a query.' if @arguments.empty?
26
37
  query = @arguments[0]
27
- if @options.minutes?
38
+
39
+ if @options[:minutes]
28
40
  granularity = 'm'
29
- elsif @options.hours?
41
+ elsif @options[:hours]
30
42
  granularity = 'h'
31
- elsif @options.seconds?
43
+ elsif @options[:seconds]
32
44
  granularity = 's'
33
- elsif @options.days?
45
+ elsif @options[:days]
34
46
  granularity = 'd'
35
47
  else
36
- puts "You must specify a granularity of either --seconds, --minutes --hours or --days. See --help for more information."
37
- exit 1
48
+ raise "You must specify a granularity of either --seconds, --minutes --hours or --days. See --help for more information."
38
49
  end
39
50
 
40
51
  unless Wavefront::Client::FORMATS.include?(@options[:format].to_sym)
41
- puts "The output format must be on of #{Wavefront::Client::FORMATS.join(', ')}"
42
- exit 1
52
+ raise "The output format must be one of: #{Wavefront::Client::FORMATS.join(', ')}."
43
53
  end
44
54
 
45
55
  options = Hash.new
@@ -47,11 +57,11 @@ class Wavefront::Cli::Ts < Wavefront::Cli
47
57
  options[:prefix_length] = @options[:prefixlength].to_i
48
58
 
49
59
  if @options[:start]
50
- options[:start_time] = Time.at(@options[:start].to_i)
60
+ options[:start_time] = parse_time(@options[:start])
51
61
  end
52
62
 
53
63
  if @options[:end]
54
- options[:end_time] = Time.at(@options[:end].to_i)
64
+ options[:end_time] = parse_time(@options[:end])
55
65
  end
56
66
 
57
67
  wave = Wavefront::Client.new(@options[:token], @options[:endpoint], @options[:debug])
@@ -60,6 +70,8 @@ class Wavefront::Cli::Ts < Wavefront::Cli
60
70
  puts wave.query(query, granularity, options)
61
71
  when :graphite
62
72
  puts wave.query(query, granularity, options).graphite.to_json
73
+ when :human
74
+ puts wave.query(query, granularity, options).human
63
75
  else
64
76
  pp wave.query(query, granularity, options)
65
77
  end
data/lib/wavefront/cli.rb CHANGED
@@ -1,4 +1,4 @@
1
- =begin
1
+ =begin
2
2
  Copyright 2015 Wavefront Inc.
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
14
14
 
15
15
  =end
16
16
 
17
+ require 'inifile'
18
+
17
19
  module Wavefront
18
20
  class Cli
19
21
 
@@ -23,11 +25,29 @@ module Wavefront
23
25
  @options = options
24
26
  @arguments = arguments
25
27
 
26
- if @options.help?
28
+ if @options[:help]
27
29
  puts @options
28
30
  exit 0
29
31
  end
30
32
  end
31
33
 
34
+ def load_profile
35
+ cf = Pathname.new(options[:config])
36
+ pf = options[:profile]
37
+
38
+ if cf.exist?
39
+ raw = IniFile.load(cf)
40
+ profile = raw[pf]
41
+
42
+ unless profile.empty?
43
+ puts "using #{pf} profile from #{cf}" if options[:debug]
44
+ return profile.inject({}){|x, (k, v)| x[k.to_sym] = v; x }
45
+ end
46
+
47
+ else
48
+ puts "no config file at '#{cf}': using options" if options[:debug]
49
+ end
50
+ end
51
+
32
52
  end
33
53
  end
@@ -16,6 +16,6 @@ See the License for the specific language governing permissions and
16
16
 
17
17
  module Wavefront
18
18
  class Client
19
- VERSION = "3.0.0"
19
+ VERSION = "3.1.0"
20
20
  end
21
21
  end
@@ -38,7 +38,7 @@ module Wavefront
38
38
 
39
39
  def query(query, granularity='m', options={})
40
40
 
41
- options[:end_time] ||= Time.now
41
+ options[:end_time] ||= Time.now.utc
42
42
  options[:start_time] ||= options[:end_time] - DEFAULT_PERIOD_SECONDS
43
43
  options[:response_format] ||= DEFAULT_FORMAT
44
44
  options[:prefix_length] ||= DEFAULT_PREFIX_LENGTH
@@ -76,6 +76,5 @@ module Wavefront
76
76
  RestClient.log = 'stdout'
77
77
  end
78
78
  end
79
-
80
79
  end
81
80
  end
@@ -1,4 +1,4 @@
1
- =begin
1
+ =begin
2
2
  Copyright 2015 Wavefront Inc.
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
@@ -22,7 +22,9 @@ module Wavefront
22
22
  DEFAULT_PREFIX_LENGTH = 1
23
23
  DEFAULT_STRICT = true
24
24
  DEFAULT_OBSOLETE_METRICS = false
25
- FORMATS = [ :raw, :ruby, :graphite, :highcharts ]
25
+ FORMATS = [ :raw, :ruby, :graphite, :highcharts, :human ]
26
+ ALERT_FORMATS = [:ruby, :json, :human]
27
+ DEFAULT_ALERT_FORMAT = :human
26
28
  GRANULARITIES = %w( s m h d )
27
29
  end
28
30
  end
@@ -1,4 +1,4 @@
1
- =begin
1
+ =begin
2
2
  Copyright 2015 Wavefront Inc.
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ module Wavefront
39
39
  class Ruby
40
40
  include JSON
41
41
  attr_reader :response, :options
42
-
42
+
43
43
  def initialize(response, options={})
44
44
  @response = response
45
45
  @options = options
@@ -59,7 +59,7 @@ module Wavefront
59
59
  def initialize(response, options={})
60
60
  super
61
61
  options[:prefix_length] ||= Wavefront::Client::DEFAULT_PREFIX_LENGTH
62
-
62
+
63
63
  @graphite = Array.new
64
64
  self.timeseries.each do |ts|
65
65
 
@@ -72,7 +72,7 @@ module Wavefront
72
72
  end
73
73
 
74
74
  output_timeseries['datapoints'] = datapoints
75
- @graphite << output_timeseries
75
+ @graphite << output_timeseries
76
76
 
77
77
  end
78
78
  end
@@ -111,5 +111,38 @@ module Wavefront
111
111
  end
112
112
  end
113
113
 
114
+ class Human < Wavefront::Response::Ruby
115
+ #
116
+ # Print "human-readable" (but also easily machine-pareseable)
117
+ # values.
118
+ #
119
+ attr_reader :response, :options, :human
120
+
121
+ def initialize(response, options={})
122
+ super
123
+
124
+ if self.respond_to?(:timeseries)
125
+ out = ['%-20s%s' % ['query', self.query]]
126
+
127
+ self.timeseries.each_with_index do |ts, i|
128
+ out.<< '%-20s%s' % ['timeseries', i]
129
+ out += ts.select{|k,v| k != 'data' }.map do |k, v|
130
+ if k == 'tags'
131
+ v.map { |tk, tv| 'tag.%-16s%s' % [tk, tv] }
132
+ else
133
+ '%-20s%s' % [k, v]
134
+ end
135
+ end
136
+ out += ts['data'].map do |t, v|
137
+ [Time.at(t).strftime('%F %T'), v].join(' ')
138
+ end
139
+ end
140
+ else
141
+ out = self.warnings
142
+ end
143
+
144
+ @human = out.join("\n")
145
+ end
146
+ end
114
147
  end
115
148
  end
@@ -1,4 +1,4 @@
1
- =begin
1
+ =begin
2
2
  Copyright 2015 Wavefront Inc.
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ Gem::Specification.new do |spec|
40
40
 
41
41
  spec.add_dependency "rest-client", ">= 1.6.7", "<= 1.8"
42
42
  spec.add_dependency "slop", ">= 3.4.7", "<= 3.6"
43
+ spec.add_dependency 'inifile', '3.0.0'
43
44
  spec.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
44
45
 
45
46
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wavefront-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Pointer
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2016-05-16 00:00:00.000000000 Z
16
+ date: 2016-05-20 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: bundler
@@ -97,6 +97,20 @@ dependencies:
97
97
  - - <=
98
98
  - !ruby/object:Gem::Version
99
99
  version: '3.6'
100
+ - !ruby/object:Gem::Dependency
101
+ name: inifile
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - '='
105
+ - !ruby/object:Gem::Version
106
+ version: 3.0.0
107
+ type: :runtime
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - '='
112
+ - !ruby/object:Gem::Version
113
+ version: 3.0.0
100
114
  description: A simple abstraction for talking to wavefront in ruby
101
115
  email:
102
116
  - support@wavefront.com