wavefront-client 3.2.0 → 3.3.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
- YmVlOTljMDc5ZWJkOTAwYzZiMDlhOTJhYTY3ZTI2YjRjNTBjZDliMw==
4
+ MDNiNGYxMWY3Y2NmNWMzM2YwY2YxNDczZDIxNGU0MGEyN2IwNDQ0MQ==
5
5
  data.tar.gz: !binary |-
6
- M2Y4ZDExZTE1NDFmNjUxZTI1NGYzOTExYzQ0ZmU2YjVhMTMzMGVmZA==
6
+ MWI3YTFiNTc2MWJlOWY3NWMyNDgwNDg1YjlkNWZiNTU0MjdhMGRkNg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NjRmYmU4NjU2NGQ0MGIwMzU4N2Q0MjQwNzQ4NWViYTJkYTZlNjk1Njk0Mzlh
10
- MWU1MTYyNDc3NzhlYzNiMDhmMjkwOWNiODExNDMwOWNlYWY5NWMzYWJhNjYw
11
- ZTdiMmVlNGYzOTY1MWQxMjZjYTUyZjA4ZjZiODY2MTI0Y2ZmZjE=
9
+ NDUwYjRjOWE3MWU4OWUzZTkyN2NiMDhiZWE4ODQ1YWU5ZDA0MWM0Mjc2OWVm
10
+ NzMxYjFiMTMzMWRiMWMyMDVkOGJlN2FmZjMyNThhYWY0YzdkMzIzZTczYTcw
11
+ ODRkMjJhOWY4M2ZiM2I1NjVhNjBmNDJjMDA4ZmRhNzlhMWEzYzA=
12
12
  data.tar.gz: !binary |-
13
- ZjUzOTZlZDlhOGY3M2NkZWU3ZDUwM2E4Y2NmNWJiNmFmZGI4MjQ4NmI1Mzk3
14
- NjZiMmQ1MTE5MzAwYmRhN2NkZTI0NTVmYjkyNDM0YzNiNWViMWNiYjExNTE1
15
- YmQ2ZTIzNzVmMTY4ZDJmNjI2YmQ1ZDg2NzYxMzIzZjJmYTY4N2M=
13
+ YTUzNTMxMzg1OTIwYzdmYWUzMDNiOTZkOGM3NzI2NTA3OWFkM2E5YzBiOGRm
14
+ ODZiNjhiNzNhMjYzODZkMDgwZDJkMGZmNGM0NmQ0NjBmYTEzMWIzNGM1ZDFl
15
+ MTU4Njk1NjFkMWRiYjBhMWM1OWEwMjFiYjA3Yzk4OGRiOThiN2E=
data/.travis.yml CHANGED
@@ -5,6 +5,7 @@ rvm:
5
5
  - 2.0.0
6
6
  - 2.1.0
7
7
  - 2.2.2
8
+ - 2.3.0
8
9
  deploy:
9
10
  provider: rubygems
10
11
  api_key:
data/README-cli.md CHANGED
@@ -12,7 +12,6 @@ The following options are valid in almost all contexts.
12
12
  ```
13
13
  -c, --config=FILE path to configuration file [default: ~/.wavefront]
14
14
  -P, --profile=NAME profile in configuration file [default: default]
15
- -E, --endpoint=URI cluster endpoint [default: metrics.wavefront.com]
16
15
  -t, --token=TOKEN Wavefront authentication token
17
16
  -D, --debug enable debug mode
18
17
  -h, --help show help for command
@@ -32,6 +31,8 @@ Usage:
32
31
  [-X bool] <query>
33
32
 
34
33
  Options:
34
+ -E, --endpoint=URI cluster endpoint [default:
35
+ metrics.wavefront.com]
35
36
  -S, --seconds query granularity of seconds
36
37
  -m, --minutes query granularity of minutes
37
38
  -H, --hours query granularity of hours
@@ -109,6 +110,7 @@ Usage:
109
110
  [-f format] [-p tag] [ -s tag] <state>
110
111
 
111
112
  Options:
113
+ -E, --endpoint=URI cluster endpoint [default: metrics.wavefront.com]
112
114
  -f, --format=STRING output format (ruby, json, human)
113
115
  [default: human]
114
116
  -p, --private=TAG retrieve only alerts with named private tags,
@@ -167,6 +169,7 @@ Usage:
167
169
  wavefront event --help
168
170
 
169
171
  Options:
172
+ -E, --endpoint=URI cluster endpoint [default: metrics.wavefront.com]
170
173
  -i, --instant create an instantaneous event
171
174
  -V, --verbose be verbose
172
175
  -s, --start=TIME time at which event begins
@@ -238,6 +241,110 @@ Closing event 'puppet_run'. [2016-06-27 19:25:16 +0100]
238
241
  Removing state file /var/tmp/wavefront/events/rob/1467051916712::puppet_run.
239
242
  ```
240
243
 
244
+ ## `write` Mode: Sending Points to Wavefront
245
+
246
+ The `write` command is used to put data points into Wavefront. It is
247
+ different from other commands in that it communicates with a
248
+ **proxy** rather than with the Wavefront API. This means it does
249
+ not require any credentials.
250
+
251
+ ```
252
+ Usage:
253
+ wavefront write point [-DV] [-c file] [-P profile] [-E proxy] [-t time]
254
+ [-p port] [-H host] [-n] [-T tag...] <metric> <value>
255
+ wavefront write file [-DV] [-c file] [-P profile] [-E proxy] [-H host]
256
+ [-p port] [-n] [-F format] [-m metric] [-T tag...] <file>
257
+
258
+ Options:
259
+ -E, --proxy=URI proxy endpoint [default: wavefront]
260
+ -t, --time=TIME time of data point (omit to use current time)
261
+ -H, --host=STRING source host [default: box]
262
+ -p, --port=INT Wavefront proxy port [default: 2878]
263
+ -T, --tag=TAG point tag in key=value form
264
+ -F, --format=STRING format of input file or stdin [default: tmv]
265
+ -n, --noop show the metric without sending it
266
+ -m, --metric=STRING the metric path to which contents of a file will be
267
+ assigned. If the file contains a metric name, the two
268
+ will be concatenated
269
+ -V, --verbose be verbose
270
+ ```
271
+
272
+ `write` has two sub-commands: `write point` and `write file`. Both
273
+ allow you to specify the proxy address and port either with
274
+ command-line switches, or by the `proxy` and `port` values in your
275
+ `.wavefront` file.
276
+
277
+ ### `write point`
278
+
279
+ This provides a very quick method of putting a point into Wavefront.
280
+ It takes two mandatory arguments: the metric path, and the metric
281
+ value.
282
+
283
+ You can optionally add point tags with multiple uses of `-T
284
+ key=val`, and specify a timestamp with the `-t` option.
285
+
286
+ ### `write file`
287
+
288
+ `write file` takes a whitespace-separated file, and turns it into a
289
+ series of points, which it sends to a Wavefront proxy. Each line
290
+ will be mapped to a single point.
291
+
292
+ Each line in the file must be of the same format, and must contain a
293
+ value. It can optionally contain metric path, a timestamp, and point
294
+ tags. The format of the file is passed in with the `-F` option, and
295
+ it must contain only the letters `t` (timestamp), `m` (metric path),
296
+ `v` (value) and `T` (point tags). If `T` is used, it must come
297
+ last: this allows you to have as many point tags as you like, and
298
+ you do not have to have the same number for each point.
299
+
300
+ The metric can also be, to some extent, described by options. If you
301
+ do not have a metric path in the file, you can use `-m` to supply a
302
+ path to which every point will be assigned. If you use `-m` *and* a
303
+ field in the file, the two will be concatenated, with `-m` used as a
304
+ global prefix.
305
+
306
+ Similarly, a global timestamp can be supplied with `-t` (timestamps
307
+ in files must be in epoch seconds, but `-t` can be any `strptime()`
308
+ parseable string), and global point tags with one or more `-T
309
+ key=val`s. If you supply tags with `-T` and in the file, the points
310
+ will get both.
311
+
312
+ The input file does not have to be on disk: following the Unix
313
+ convention, you can use `-` as the filename, and `wavefront` will
314
+ read from standard in, converting lines to points as it receives
315
+ them. All the same rules apply as with standard files.
316
+
317
+ `wavefront write file` takes some efforts to protect the user from
318
+ sending bad data. It will not allow metrics with less than two
319
+ components, and it will not permit timestamps prior to 2000-01-01,
320
+ or more than a year in the future. It also checks that every
321
+ potential data point conforms to the limits described in the
322
+ Wavefront wire format documentation.
323
+
324
+ ### Examples
325
+
326
+ Tell Wavefront that the value of `dev.myvalue` at this moment is
327
+ 123.
328
+
329
+ ```
330
+ $ wavefront write point dev.myvalue 123
331
+ ```
332
+
333
+ Write a file of retrospective data, whwere the fields are, in order,
334
+ a timestamp, the metric path, and the value. Tag all points with
335
+ `mytag` set to `my value`.
336
+
337
+ ```
338
+ $ wavefront write file -F tmvT -T mytag="my value" datafile
339
+ ```
340
+
341
+ The command `parabola.rb` prints a timestamp and a 'y' value every
342
+ second. Plot the parabola in Wavefront.
343
+
344
+ ```
345
+ $ parabola.rb | wavefront write file -F tv -m cli.demo.parabola -
346
+ ```
347
+
241
348
  ## Notes on Options
242
349
 
243
350
  ### Times
data/bin/wavefront CHANGED
@@ -18,11 +18,12 @@ require 'pathname'
18
18
  require 'wavefront/client'
19
19
  require 'wavefront/cli'
20
20
  require 'docopt'
21
+ require 'socket'
21
22
  include Wavefront::Constants
22
23
 
23
24
  def sanitize_keys(hash)
24
25
  hash.each_with_object({}) do |(k, v), aggr|
25
- aggr[k.gsub(/-/, '').to_sym] = v
26
+ aggr[k.delete('-').to_sym] = v
26
27
  end
27
28
  end
28
29
 
@@ -31,12 +32,10 @@ DEF_CF = Pathname.new(ENV['HOME']) + '.wavefront'
31
32
 
32
33
  # The global_opts are available in every command.
33
34
  #
34
- global_opts = %Q(
35
+ global_opts = %(
35
36
  Global options:
36
37
  -c, --config=FILE path to configuration file [default: #{DEF_CF}]
37
38
  -P, --profile=NAME profile in configuration file [default: default]
38
- -E, --endpoint=URI cluster endpoint [default: #{DEFAULT_HOST}]
39
- -t, --token=TOKEN Wavefront authentication token
40
39
  -D, --debug enable debug mode
41
40
  -h, --help show this message
42
41
  )
@@ -45,13 +44,15 @@ Global options:
45
44
  # commands we offer. They must include the global_opts.
46
45
  #
47
46
  usage = {
48
- ts: %Q(
47
+ ts: %(
49
48
  Usage:
50
49
  #{ME} ts [-c file] [-P profile] [-E endpoint] [-t token] [-OD]
51
50
  [-S | -m | -H | -d] [-s time] [-e time] [-f format] [-p num]
52
51
  [-X bool] <query>
53
52
  #{global_opts}
54
53
  Options:
54
+ -E, --endpoint=URI cluster endpoint [default: #{DEFAULT_HOST}]
55
+ -t, --token=TOKEN Wavefront authentication token
55
56
  -S, --seconds query granularity of seconds
56
57
  -m, --minutes query granularity of minutes
57
58
  -H, --hours query granularity of hours
@@ -69,12 +70,14 @@ Options:
69
70
  -O, --includeObsoleteMetrics include metrics unreported for > 4 weeks
70
71
  ),
71
72
 
72
- alerts: %Q(
73
+ alerts: %(
73
74
  Usage:
74
75
  #{ME} alerts [-c file] [-P profile] [-E endpoint] [-t token]
75
76
  [-f format] [-p tag] [ -s tag] <state>
76
77
  #{global_opts}
77
78
  Options:
79
+ -E, --endpoint=URI cluster endpoint [default: #{DEFAULT_HOST}]
80
+ -t, --token=TOKEN Wavefront authentication token
78
81
  -f, --format=STRING output format (#{ALERT_FORMATS.join(', ')})
79
82
  [default: #{DEFAULT_ALERT_FORMAT}]
80
83
  -p, --private=TAG retrieve only alerts with named private tags,
@@ -83,10 +86,10 @@ Options:
83
86
  delimited.
84
87
  ),
85
88
 
86
- event: %Q(
89
+ event: %(
87
90
  Usage:
88
91
  #{ME} event create [-V] [-c file] [-P profile] [-E endpoint] [-t token]
89
- [-d description] [-s time] [-i | -e time] [-l level] [-t type]
92
+ [-d description] [-s time] [-i | -e time] [-l level] [-T type]
90
93
  [-H host] [-n] <event>
91
94
  #{ME} event close [-V] [-c file] [-P profile] [-E endpoint] [-t token]
92
95
  [<event>] [<timestamp>]
@@ -106,7 +109,33 @@ Options:
106
109
 
107
110
  View events in detail using the 'ts' command with the 'events()' function.
108
111
  ),
109
- default: %Q(
112
+
113
+ write: %(
114
+ Usage:
115
+ #{ME} write point [-DV] [-c file] [-P profile] [-E proxy] [-t time]
116
+ [-p port] [-H host] [-n] [-T tag...] <metric> <value>
117
+ #{ME} write file [-DV] [-c file] [-P profile] [-E proxy] [-H host]
118
+ [-p port] [-n] [-F format] [-m metric] [-T tag...] <file>
119
+ #{ME} write --help
120
+ #{global_opts}
121
+ Options:
122
+ -E, --proxy=URI proxy endpoint [default: #{DEFAULT_PROXY}]
123
+ -t, --time=TIME time of data point (omit to use current time)
124
+ -H, --host=STRING source host [default: #{Socket.gethostname}]
125
+ -p, --port=INT Wavefront proxy port [default: #{DEFAULT_PROXY_PORT}]
126
+ -T, --tag=TAG point tag in key=value form
127
+ -F, --format=STRING format of input file or stdin [default: #{DEFAULT_INFILE_FORMAT}]
128
+ -n, --noop show the metric without sending it
129
+ -m, --metric=STRING the metric path to which contents of a file will be
130
+ assigned. If the file contains a metric name, the two
131
+ will be concatenated
132
+ -V, --verbose be verbose
133
+
134
+ Files are whitespace separated, and fields can be defined with the -F
135
+ option. Use 't' for timestamp; 'm' for metric name; 'v' for value
136
+ and 'T' for tags. Put 'T' last.
137
+ ),
138
+ default: %(
110
139
  Wavefront CLI
111
140
 
112
141
  Usage:
@@ -118,6 +147,7 @@ Commands:
118
147
  ts view timeseries data
119
148
  alerts view alerts
120
149
  event open and close events
150
+ write send data points to a Wavefront proxy
121
151
 
122
152
  Use '#{ME} <command> --help' for further information.)
123
153
  }
@@ -126,13 +156,13 @@ Use '#{ME} <command> --help' for further information.)
126
156
  # help/option parser generation.
127
157
  #
128
158
  begin
129
- opts = Docopt::docopt(usage[:default], version: '3.2.0')
159
+ opts = Docopt.docopt(usage[:default], version: '3.2.0')
130
160
  rescue Docopt::Exit => e
131
161
  cmd = ARGV.length > 0 ? ARGV.first.to_sym : nil
132
162
 
133
163
  if usage.keys.include?(cmd)
134
164
  begin
135
- opts = sanitize_keys(Docopt::docopt(usage[cmd]))
165
+ opts = sanitize_keys(Docopt.docopt(usage[cmd]))
136
166
  rescue Docopt::Exit => e
137
167
  abort e.message
138
168
  end
@@ -156,6 +186,14 @@ when :event
156
186
  when :alerts
157
187
  require 'wavefront/cli/alerts'
158
188
  cli = Wavefront::Cli::Alerts.new(opts, [opts[:'<state>']])
189
+ when :write
190
+ if opts[:file]
191
+ require 'wavefront/cli/batch_write'
192
+ cli = Wavefront::Cli::BatchWrite.new(opts, [opts[:'<state>']])
193
+ else
194
+ require 'wavefront/cli/write'
195
+ cli = Wavefront::Cli::Write.new(opts, [opts[:'<state>']])
196
+ end
159
197
  end
160
198
 
161
199
  begin
@@ -0,0 +1,247 @@
1
+ require 'wavefront/client/version'
2
+ require 'wavefront/exception'
3
+ require 'wavefront/constants'
4
+ require 'uri'
5
+ require 'socket'
6
+
7
+ HOSTNAME = Socket.gethostname
8
+
9
+ module Wavefront
10
+ #
11
+ # This class exists to facilitate sending of multiple data points
12
+ # to a Wavefront proxy. It sends points in native Wavefront
13
+ # format.
14
+ #
15
+ # When initializing the instance you can
16
+ # define point tags which will apply to all points sent via that
17
+ # instance.
18
+ #
19
+ # Though we provide methods to do it, it is the developer's
20
+ # responsibility to open and close the socket to the proxy. Points
21
+ # are sent by calling the write() method.
22
+ #
23
+ # The class keeps a count of the points the current instance has
24
+ # sent, dropped, and failed to send, in @summary. The socket is accessed
25
+ # through the instance variable @sock.
26
+ #
27
+ class BatchWriter
28
+ attr_reader :sock, :opts, :summary
29
+ include Wavefront::Constants
30
+
31
+ def initialize(options = {})
32
+ #
33
+ # options is of the form:
34
+ #
35
+ # {
36
+ # tags: a key-value hash of tags which will be applied to
37
+ # every point
38
+ # proxy: the address of the Wavefront proxy
39
+ # port: the port of the Wavefront proxy
40
+ # noop: if this is true, no proxy connection will be made,
41
+ # and instead of sending the points, they will
42
+ # be printed in Wavefront wire format.
43
+ # novalidate: if this is true, points will not be validated.
44
+ # This might make things go marginally quicker
45
+ # if you have done point validation higher up in
46
+ # the chain.
47
+ # verbose: if this is true, many of the methods will report
48
+ # their progress.
49
+ # debug: if this is true, debugging output will be
50
+ # printed.
51
+ # }
52
+ #
53
+ defaults = {
54
+ tags: false,
55
+ proxy: DEFAULT_PROXY,
56
+ port: DEFAULT_PROXY_PORT,
57
+ noop: false,
58
+ novalidate: false,
59
+ verbose: false,
60
+ debug: false,
61
+ }
62
+
63
+ @summary = { sent: 0,
64
+ rejected: 0,
65
+ unsent: 0,
66
+ }
67
+ @opts = setup_options(options, defaults)
68
+
69
+ if opts[:tags]
70
+ valid_tags?(opts[:tags])
71
+ @global_tags = opts[:tags]
72
+ end
73
+ end
74
+
75
+ def setup_options(user, defaults)
76
+ #
77
+ # Fill in some defaults, if the user hasn't supplied them
78
+ #
79
+ defaults.merge(user)
80
+ end
81
+
82
+ def write(points = [], options = {})
83
+ #
84
+ # Points are defined as hashes of the following form:
85
+ # {
86
+ # path: metrics path. String. Mandatory.
87
+ # value: value of metric. Numeric. Mandatory.
88
+ # ts: timestamp as a Time or Date object. default:
89
+ # Time.now. May be omitted or false.
90
+ # source: originating source of metric. default: `hostname`
91
+ # tags: optional hash of key: value point tags
92
+ # }
93
+ #
94
+ # Send multiple points by using an array of the above hashes.
95
+ #
96
+ unless points.is_a?(Hash) || points.is_a?(Array)
97
+ summary[:rejected] += 1
98
+ return false
99
+ end
100
+
101
+ points = [points] if points.is_a?(Hash)
102
+
103
+ points.each do |p|
104
+ p[:ts] = Time.at(p[:ts]) if p[:ts].is_a?(Integer)
105
+ begin
106
+ valid_point?(p)
107
+ rescue Wavefront::Exception::InvalidMetricName,
108
+ Wavefront::Exception::InvalidMetricValue,
109
+ Wavefront::Exception::InvalidTimestamp,
110
+ Wavefront::Exception::InvalidSource,
111
+ Wavefront::Exception::InvalidTag => e
112
+ puts 'Invalid point, skipping.' if opts[:verbose]
113
+ puts "Invalid point: #{p}. (#{e})" if opts[:debug]
114
+ summary[:rejected] += 1
115
+ next
116
+ end
117
+
118
+ send_point(hash_to_wf(p))
119
+ end
120
+ return summary[:rejected] == 0 ? true : false
121
+ end
122
+
123
+ def valid_point?(point)
124
+ #
125
+ # Validate a point so it conforms to the standard described in
126
+ # https://community.wavefront.com/docs/DOC-1031
127
+ #
128
+ return true if opts.key?(:novalidate) && opts[:novalidate]
129
+ valid_path?(point[:path])
130
+ valid_value?(point[:value])
131
+ valid_ts?(point[:ts]) if point[:ts]
132
+ valid_source?(point[:source])
133
+ valid_tags?(point[:tags]) if point[:tags] && point[:tags].length > 0
134
+ true
135
+ end
136
+
137
+ def valid_path?(path)
138
+ fail Wavefront::Exception::InvalidMetricName unless \
139
+ path.is_a?(String) && path.match(/^[a-z0-9\-_\.]+$/) &&
140
+ path.length < 1024
141
+ true
142
+ end
143
+
144
+ def valid_value?(value)
145
+ fail Wavefront::Exception::InvalidMetricValue unless value.is_a?(Numeric)
146
+ true
147
+ end
148
+
149
+ def valid_ts?(ts)
150
+ unless ts.is_a?(Time) || ts.is_a?(Date)
151
+ fail Wavefront::Exception::InvalidTimestamp
152
+ end
153
+ true
154
+ end
155
+
156
+ def valid_source?(path)
157
+ unless path.is_a?(String) && path.match(/^[a-z0-9\-_\.]+$/) &&
158
+ path.length < 1024
159
+ fail Wavefront::Exception::InvalidSource
160
+ end
161
+ true
162
+ end
163
+
164
+ def valid_tags?(tags)
165
+ tags.each do |k, v|
166
+ fail Wavefront::Exception::InvalidTag unless (k.length +
167
+ v.length < 254) && k.match(/^[a-z0-9\-_\.]+$/)
168
+ end
169
+ true
170
+ end
171
+
172
+ def hash_to_wf(p)
173
+ #
174
+ # Convert the hash received by the write() method to a string
175
+ # conforming with that defined in
176
+ # https://community.wavefront.com/docs/DOC-1031
177
+ #
178
+ fail ArgumentError unless p.key?(:path) && p.key?(:value) &&
179
+ p.key?(:source)
180
+
181
+ m = [p[:path], p[:value]]
182
+ m.<< p[:ts].to_i.to_s if p.key?(:ts) && p[:ts]
183
+ m.<< 'source=' + p[:source]
184
+ m.<< tag_hash_to_str(p[:tags]) if p.key?(:tags) && p[:tags]
185
+ m.<< tag_hash_to_str(opts[:tags]) if opts[:tags]
186
+ m.join(' ')
187
+ end
188
+
189
+ def tag_hash_to_str(tags)
190
+ #
191
+ # Convert a hash of tags into a string of key="val" tags. The
192
+ # quoting is recommended in the WF wire-format guide. No tag
193
+ # validation is done here: we assume you used valid_tags()
194
+ #
195
+ return '' unless tags.is_a?(Hash)
196
+ tags.map { |k, v| "#{k}=\"#{v}\"" }.join(' ')
197
+ end
198
+
199
+ def send_point(point)
200
+ #
201
+ # Send a point, which should already be in Wavefront wire
202
+ # format.
203
+ #
204
+ if opts[:noop]
205
+ puts "Would send: #{point}"
206
+ return
207
+ end
208
+
209
+ puts "Sending: #{point}" if opts[:verbose] || opts[:debug]
210
+
211
+ begin
212
+ sock.puts(point)
213
+ summary[:sent] += 1
214
+ return true
215
+ rescue
216
+ summary[:unsent] += 1
217
+ puts 'WARNING: failed to send point.'
218
+ return false
219
+ end
220
+ end
221
+
222
+ def open_socket
223
+ #
224
+ # Open a socket to a Wavefront proxy, putting the descriptor
225
+ # in instance variable @sock.
226
+ #
227
+ if opts[:noop]
228
+ puts 'No-op requested. Not opening connection to proxy.'
229
+ return true
230
+ end
231
+
232
+ puts "Connecting to #{opts[:proxy]}:#{opts[:port]}." if opts[:verbose]
233
+
234
+ begin
235
+ @sock = TCPSocket.new(opts[:proxy], opts[:port])
236
+ rescue
237
+ raise Wavefront::Exception::InvalidEndpoint
238
+ end
239
+ end
240
+
241
+ def close_socket
242
+ return if opts[:noop]
243
+ puts 'Closing connection to proxy.' if opts[:verbose]
244
+ sock.close
245
+ end
246
+ end
247
+ end