ffwd-google-cloud 0.4.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c105cd9903f52b23602bfb3b6c21aa0a25e02294
4
+ data.tar.gz: 41cc39f9192c0301fb2c450e9b5c214b4254b824
5
+ SHA512:
6
+ metadata.gz: 2b4cb5bdf6522e2e2b3a318fd57077f5962e7a3d8666ecd847e5abb6d41f03080466ad45532aa0844f5be38847c4511c44eb7309a94ab9f7c3931b4811abd729
7
+ data.tar.gz: 48ed69dc4005e1d82935c73894210ded2df4071136b682ee4d42ef6f16db4cc9e5482a72e7421b91774dba56460138d92f3f8bbeb2b1b041c7dc42738c5cee7a
@@ -0,0 +1,191 @@
1
+ # $LICENSE
2
+ # Copyright 2013-2014 Spotify AB. All rights reserved.
3
+ #
4
+ # The contents of this file are licensed under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ require 'json'
17
+
18
+ require_relative 'utils'
19
+
20
+ require 'ffwd/flushing_output_hook'
21
+
22
+ module FFWD::Plugin::GoogleCloud
23
+ class Hook < FFWD::FlushingOutputHook
24
+ include FFWD::Logging
25
+
26
+ HEADER_BASE = {
27
+ "Content-Type" => "application/json"
28
+ }
29
+
30
+ def initialize c
31
+ @api_url = c[:api_url]
32
+ @metadata_url = c[:metadata_url]
33
+ @project_id = c[:project_id]
34
+ @project = c[:project]
35
+ @client_id = c[:client_id]
36
+ @scope = c[:scope]
37
+
38
+ @api_c = nil
39
+ @metadata_c = nil
40
+ @token = nil
41
+ @expires_at = nil
42
+ # list of blocks waiting for a token.
43
+ @pending = []
44
+
45
+ @api = "/cloudmonitoring/v2beta2/projects/#{@project_id}/timeseries:write"
46
+ @acquire = "/0.1/meta-data/service-accounts/default/acquire"
47
+ @expire_threshold = 10
48
+ end
49
+
50
+ def with_token &block
51
+ # join a pending call
52
+ unless @pending.empty?
53
+ proxy = CallbackProxy.new
54
+ @pending << [block, proxy]
55
+ return proxy
56
+ end
57
+
58
+ # cached, valid token
59
+ if @token and Time.now + @expire_threshold < @expires_at
60
+ return block.call(@token)
61
+ end
62
+
63
+ current_p = CallbackProxy.new
64
+ @pending << [block, current_p]
65
+
66
+ log.debug "Requesting token"
67
+
68
+ http = @metadata_c.get(
69
+ :path => @acquire,
70
+ :query => {:client_id => @client_id, :scope => @scope})
71
+
72
+ token_p = new_proxy(http)
73
+
74
+ token_p.errback do
75
+ @pending.each do |b, block_p|
76
+ block_p.err "Token request failed: #{token_p.error}"
77
+ end.clear
78
+ end
79
+
80
+ token_p.callback do
81
+ result = JSON.load(http.response)
82
+
83
+ @token = result['accessToken']
84
+ @expires_at = Time.at(result['expiresAt'])
85
+
86
+ log.debug "Got token: #{@token} (expires_at: #{@expires_at}}"
87
+
88
+ @pending.each do |b, block_p|
89
+ b.call(@token).into block_p
90
+ end.clear
91
+ end
92
+
93
+ return current_p
94
+ end
95
+
96
+ def active?
97
+ not @api_c.nil? and not @metadata_c.nil?
98
+ end
99
+
100
+ def connect
101
+ @metadata_c = EM::HttpRequest.new(@metadata_url)
102
+ @api_c = EM::HttpRequest.new(@api_url)
103
+ end
104
+
105
+ def close
106
+ @metadata_c.close if @metadata_c
107
+ @api_c.close if @api_c
108
+
109
+ @metadata_c = nil
110
+ @api_c = nil
111
+ end
112
+
113
+ def send metrics
114
+ request = {
115
+ "timeseries" => Utils.make_timeseries(metrics)
116
+ }
117
+
118
+ metrics = JSON.dump(request)
119
+
120
+ with_token do |token|
121
+ head = Hash[HEADER_BASE]
122
+ head['Authorization'] = "Bearer #{token}"
123
+
124
+ if log.debug?
125
+ log.debug "Sending: #{metrics}"
126
+ end
127
+
128
+ new_proxy @api_c.post(:path => @api, :head => head, :body => metrics)
129
+ end
130
+ end
131
+
132
+ # Setup a new proxy object for http request.
133
+ # This makes sure that the callback/errback/error api as is expected by
134
+ # flushing_output to be consistent.
135
+ def new_proxy http
136
+ bind_proxy http, CallbackProxy.new
137
+ end
138
+
139
+ def bind_proxy http, p
140
+ http.errback do
141
+ p.err "#{http.error}"
142
+ end
143
+
144
+ http.callback do
145
+ if http.response_header.status == 200
146
+ p.call
147
+ else
148
+ p.err "#{http.response_header.status}: #{http.response}"
149
+ end
150
+ end
151
+
152
+ p
153
+ end
154
+
155
+ def reporter_meta
156
+ {:component => :google_cloud}
157
+ end
158
+ end
159
+
160
+ class CallbackProxy
161
+ attr_reader :error
162
+
163
+ def initialize
164
+ @callbacks = []
165
+ @errbacks = []
166
+ end
167
+
168
+ def callback &block
169
+ @callbacks << block
170
+ end
171
+
172
+ def errback &block
173
+ @errbacks << block
174
+ end
175
+
176
+ def call
177
+ @callbacks.each(&:call).clear
178
+ end
179
+
180
+ def err error
181
+ return if @errbacks.empty?
182
+ @error = error
183
+ @errbacks.each(&:call).clear
184
+ end
185
+
186
+ def into other
187
+ errback { other.err error }
188
+ callback { other.call }
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,39 @@
1
+ # $LICENSE
2
+ # Copyright 2013-2014 Spotify AB. All rights reserved.
3
+ #
4
+ # The contents of this file are licensed under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ module FFWD::Plugin::GoogleCloud
17
+ module Utils
18
+ def self.make_timeseries buffer
19
+ buffer.map do |m|
20
+ {:timeseriesDesc => make_desc(m), :point => make_point(m)}
21
+ end
22
+ end
23
+
24
+ def self.make_point m
25
+ time = m.time.utc.strftime('%FT%TZ')
26
+ {:start => time, :end => time, :doubleValue => m.value}
27
+ end
28
+
29
+ def self.make_desc m
30
+ {:metric => m.key, :labels => make_labels(m)}
31
+ end
32
+
33
+ def self.make_labels m
34
+ labels = Hash[m.attributes]
35
+ labels["host"] = m.host
36
+ labels
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ # $LICENSE
2
+ # Copyright 2013-2014 Spotify AB. All rights reserved.
3
+ #
4
+ # The contents of this file are licensed under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ module FFWD
17
+ module Plugin
18
+ module GoogleCloud
19
+ VERSION = "0.4.0"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,61 @@
1
+ # $LICENSE
2
+ # Copyright 2013-2014 Spotify AB. All rights reserved.
3
+ #
4
+ # The contents of this file are licensed under the Apache License, Version 2.0
5
+ # (the "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ require 'eventmachine'
17
+ require 'em-http'
18
+
19
+ require 'ffwd/logging'
20
+ require 'ffwd/plugin'
21
+ require 'ffwd/reporter'
22
+ require 'ffwd/flushing_output'
23
+
24
+ require_relative 'google_cloud/hook'
25
+
26
+ module FFWD::Plugin::GoogleCloud
27
+ include FFWD::Plugin
28
+ include FFWD::Logging
29
+
30
+ register_plugin "google-cloud"
31
+
32
+ DEFAULT_API_URL = "https://www.googleapis.com"
33
+ DEFAULT_METADATA_URL = "http://metadata.google.internal"
34
+ DEFAULT_SCOPE = "https://www.googleapis.com/auth/monitoring"
35
+ DEFAULT_FLUSH_INTERVAL = 10
36
+ DEFAULT_BUFFER_LIMIT = 100
37
+
38
+ def self.setup_output config
39
+ if not config[:project_id]
40
+ raise "'project_id' is required"
41
+ end
42
+
43
+ if not config[:project]
44
+ raise "'project' is required"
45
+ end
46
+
47
+ if not config[:client_id]
48
+ raise "'client_id' is required"
49
+ end
50
+
51
+ config[:scope] ||= DEFAULT_SCOPE
52
+ config[:metadata_url] ||= DEFAULT_METADATA_URL
53
+ config[:api_url] ||= DEFAULT_API_URL
54
+ config[:flush_interval] ||= DEFAULT_FLUSH_INTERVAL
55
+ config[:buffer_limit] ||= DEFAULT_BUFFER_LIMIT
56
+
57
+ hook = Hook.new(config)
58
+
59
+ FFWD.flushing_output log, hook, config
60
+ end
61
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ffwd-google-cloud
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - John-John Tedro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: em-http-request
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ffwd
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.4.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-mocks
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - udoprog@spotify.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - lib/ffwd/plugin/google_cloud/hook.rb
77
+ - lib/ffwd/plugin/google_cloud/utils.rb
78
+ - lib/ffwd/plugin/google_cloud/version.rb
79
+ - lib/ffwd/plugin/google_cloud.rb
80
+ homepage: https://github.com/spotify/ffwd
81
+ licenses:
82
+ - Apache 2.0
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.0.14
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Google Cloud Monitoring support for FFWD.
104
+ test_files: []