google-cloud-logging 0.20.1 → 0.21.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.
@@ -0,0 +1,121 @@
1
+ # Copyright 2016 Google Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "google/cloud/logging"
16
+
17
+ module Google
18
+ module Cloud
19
+ module Logging
20
+ ##
21
+ # Default log name to be used for Stackdriver Logging
22
+ DEFAULT_LOG_NAME = "ruby_app_log"
23
+
24
+ ##
25
+ # Railtie
26
+ #
27
+ # Google::Cloud::Logging::Railtie automatically add the
28
+ # Google::Cloud::Logging::Middleware to Rack in a Rails environment.
29
+ # The middleware will set env['rack.logger'] to a
30
+ # Google::Cloud::Logging::Logger instance to be used by the Rails
31
+ # application.
32
+ #
33
+ # The Middleware is only added when certain conditions are met. See
34
+ # {use_logging?} for detail.
35
+ #
36
+ # When loaded, the Google::Cloud::Logging::Middleware will be inserted
37
+ # before the Rails::Rack::Logger Middleware, which allows it to set the
38
+ # env['rack.logger'] in place of Rails's default logger. The Railtie
39
+ # should also initialize the logger with correct GCP project_id
40
+ # and keyfile if they are defined in Rails environment.rb as follow:
41
+ # config.google_cloud.logging.project_id = "my-gcp-project"
42
+ # config.google_cloud.logging.keyfile = "/path/to/secret.json"
43
+ # or
44
+ # config.google_cloud.project_id = "my-gcp-project"
45
+ # config.google_cloud.keyfile = "/path/to/secret.json"
46
+ # If omitted, project_id will be initialized with default environment
47
+ # variables.
48
+ #
49
+ class Railtie < ::Rails::Railtie
50
+ config.google_cloud = ::ActiveSupport::OrderedOptions.new unless
51
+ config.respond_to? :google_cloud
52
+ config.google_cloud.logging = ::ActiveSupport::OrderedOptions.new
53
+
54
+ initializer "Stackdriver.Logging", before: :initialize_logger do |app|
55
+ if self.class.use_logging? app.config
56
+ gcp_config = app.config.google_cloud
57
+ log_config = gcp_config.logging
58
+
59
+ project_id = log_config.project_id || gcp_config.project_id
60
+ keyfile = log_config.keyfile || gcp_config.keyfile
61
+
62
+ logging = Google::Cloud::Logging.new project: project_id,
63
+ keyfile: keyfile
64
+ resource =
65
+ Google::Cloud::Logging::Middleware.build_monitoring_resource
66
+ log_name = log_config.log_name || DEFAULT_LOG_NAME
67
+
68
+ app.config.logger = Google::Cloud::Logging::Logger.new logging,
69
+ log_name,
70
+ resource
71
+ app.middleware.insert_before Rails::Rack::Logger,
72
+ Google::Cloud::Logging::Middleware,
73
+ logger: app.config.logger
74
+ end
75
+ end
76
+
77
+ ##
78
+ # Determine whether to use Stackdriver Logging or not.
79
+ #
80
+ # Returns true if valid GCP project_id is provided and underneath API is
81
+ # able to authenticate. Also either Rails needs to be in "production"
82
+ # environment or config.stackdriver.use_logging is explicitly true.
83
+ #
84
+ # @param config The Rails.application.config
85
+ #
86
+ # @return [Boolean]
87
+ #
88
+ def self.use_logging? config
89
+ gcp_config = config.google_cloud
90
+ # Return false if config.stackdriver.use_logging is explicitly false
91
+ return false if gcp_config.key?(:use_logging) &&
92
+ !gcp_config.use_logging
93
+
94
+ # Try authenticate authorize client API. Return false if unable to
95
+ # authorize.
96
+ keyfile = gcp_config.logging.keyfile || gcp_config.keyfile
97
+ begin
98
+ Google::Cloud::Logging::Credentials.credentials_with_scope keyfile
99
+ rescue Exception => e
100
+ warn "Unable to initialize Google::Cloud::Logging due " \
101
+ "to authorization error: #{e.message}"
102
+ return false
103
+ end
104
+
105
+ project_id = gcp_config.logging.project_id || gcp_config.project_id ||
106
+ Google::Cloud::Logging::Project.default_project
107
+ if project_id.to_s.empty?
108
+ warn "Unable to initialize Google::Cloud::Logging with empty " \
109
+ "project_id"
110
+ return false
111
+ end
112
+
113
+ # Otherwise default to true if Rails is running in production or
114
+ # config.stackdriver.use_logging is explicitly true
115
+ Rails.env.production? ||
116
+ (gcp_config.key?(:use_logging) && gcp_config.use_logging)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -30,10 +30,9 @@ module Google
30
30
  # {Google::Cloud::Logging::Project#write_entries}.
31
31
  #
32
32
  # @example
33
- # require "google/cloud"
33
+ # require "google/cloud/logging"
34
34
  #
35
- # gcloud = Google::Cloud.new
36
- # logging = gcloud.logging
35
+ # logging = Google::Cloud::Logging.new
37
36
  # resource = logging.resource "gae_app",
38
37
  # "module_id" => "1",
39
38
  # "version_id" => "20150925t173233"
@@ -31,10 +31,9 @@ module Google
31
31
  # instances, but you can list them with {Project#resource_descriptors}.
32
32
  #
33
33
  # @example
34
- # require "google/cloud"
34
+ # require "google/cloud/logging"
35
35
  #
36
- # gcloud = Google::Cloud.new
37
- # logging = gcloud.logging
36
+ # logging = Google::Cloud::Logging.new
38
37
  # resource_descriptor = logging.resource_descriptors.first
39
38
  # resource_descriptor.type #=> "cloudsql_database"
40
39
  # resource_descriptor.name #=> "Cloud SQL Database"
@@ -93,10 +92,9 @@ module Google
93
92
  # their `database_id`. See {ResourceDescriptor#labels}.
94
93
  #
95
94
  # @example
96
- # require "google/cloud"
95
+ # require "google/cloud/logging"
97
96
  #
98
- # gcloud = Google::Cloud.new
99
- # logging = gcloud.logging
97
+ # logging = Google::Cloud::Logging.new
100
98
  # resource_descriptor = logging.resource_descriptors.first
101
99
  # label_descriptor = resource_descriptor.labels.first
102
100
  # label_descriptor.key #=> "database_id"
@@ -41,10 +41,9 @@ module Google
41
41
  # @return [Boolean]
42
42
  #
43
43
  # @example
44
- # require "google/cloud"
44
+ # require "google/cloud/logging"
45
45
  #
46
- # gcloud = Google::Cloud.new
47
- # logging = gcloud.logging
46
+ # logging = Google::Cloud::Logging.new
48
47
  #
49
48
  # resource_descriptors = logging.resource_descriptors
50
49
  # if resource_descriptors.next?
@@ -61,10 +60,9 @@ module Google
61
60
  # @return [Sink::List]
62
61
  #
63
62
  # @example
64
- # require "google/cloud"
63
+ # require "google/cloud/logging"
65
64
  #
66
- # gcloud = Google::Cloud.new
67
- # logging = gcloud.logging
65
+ # logging = Google::Cloud::Logging.new
68
66
  #
69
67
  # resource_descriptors = logging.resource_descriptors
70
68
  # if resource_descriptors.next?
@@ -100,10 +98,9 @@ module Google
100
98
  # @return [Enumerator]
101
99
  #
102
100
  # @example Iterating each resource descriptor by passing a block:
103
- # require "google/cloud"
101
+ # require "google/cloud/logging"
104
102
  #
105
- # gcloud = Google::Cloud.new
106
- # logging = gcloud.logging
103
+ # logging = Google::Cloud::Logging.new
107
104
  # resource_descriptors = logging.resource_descriptors
108
105
  #
109
106
  # resource_descriptors.all do |rd|
@@ -111,10 +108,9 @@ module Google
111
108
  # end
112
109
  #
113
110
  # @example Using the enumerator by not passing a block:
114
- # require "google/cloud"
111
+ # require "google/cloud/logging"
115
112
  #
116
- # gcloud = Google::Cloud.new
117
- # logging = gcloud.logging
113
+ # logging = Google::Cloud::Logging.new
118
114
  # resource_descriptors = logging.resource_descriptors
119
115
  #
120
116
  # all_types = resource_descriptors.all.map do |rd|
@@ -122,10 +118,9 @@ module Google
122
118
  # end
123
119
  #
124
120
  # @example Limit the number of API calls made:
125
- # require "google/cloud"
121
+ # require "google/cloud/logging"
126
122
  #
127
- # gcloud = Google::Cloud.new
128
- # logging = gcloud.logging
123
+ # logging = Google::Cloud::Logging.new
129
124
  # resource_descriptors = logging.resource_descriptors
130
125
  #
131
126
  # resource_descriptors.all(request_limit: 10) do |rd|
@@ -14,10 +14,8 @@
14
14
 
15
15
 
16
16
  require "google/cloud/errors"
17
- require "google/cloud/core/grpc_backoff"
18
- require "google/logging/v2/logging_pb"
19
- require "google/logging/v2/logging_config_pb"
20
- require "google/logging/v2/logging_metrics_pb"
17
+ require "google/cloud/logging/v2"
18
+ require "google/gax/errors"
21
19
 
22
20
  module Google
23
21
  module Cloud
@@ -26,69 +24,92 @@ module Google
26
24
  # @private Represents the gRPC Logging service, including all the API
27
25
  # methods.
28
26
  class Service
29
- attr_accessor :project, :credentials, :host, :retries, :timeout
27
+ attr_accessor :project, :credentials, :host, :timeout, :client_config
30
28
 
31
29
  ##
32
30
  # Creates a new Service instance.
33
- def initialize project, credentials, host: nil, retries: nil,
34
- timeout: nil
31
+ def initialize project, credentials, host: nil, timeout: nil,
32
+ client_config: nil
35
33
  @project = project
36
34
  @credentials = credentials
37
- @host = host || "logging.googleapis.com"
38
- @retries = retries
35
+ @host = host || V2::LoggingServiceV2Api::SERVICE_ADDRESS
39
36
  @timeout = timeout
37
+ @client_config = client_config || {}
40
38
  end
41
39
 
42
- def creds
40
+ def channel
41
+ require "grpc"
42
+ GRPC::Core::Channel.new host, nil, chan_creds
43
+ end
44
+
45
+ def chan_creds
46
+ return credentials if insecure?
47
+ require "grpc"
43
48
  GRPC::Core::ChannelCredentials.new.compose \
44
49
  GRPC::Core::CallCredentials.new credentials.client.updater_proc
45
50
  end
46
51
 
47
52
  def logging
48
53
  return mocked_logging if mocked_logging
49
- @logging ||= begin
50
- require "google/logging/v2/logging_services_pb"
51
-
52
- Google::Logging::V2::LoggingServiceV2::Stub.new(
53
- host, creds, timeout: timeout)
54
- end
54
+ @logging ||= \
55
+ V2::LoggingServiceV2Api.new(
56
+ service_path: host,
57
+ channel: channel,
58
+ timeout: timeout,
59
+ client_config: client_config,
60
+ app_name: "gcloud-ruby",
61
+ app_version: Google::Cloud::Logging::VERSION)
55
62
  end
56
63
  attr_accessor :mocked_logging
57
64
 
58
65
  def sinks
59
66
  return mocked_sinks if mocked_sinks
60
- @sinks ||= begin
61
- require "google/logging/v2/logging_config_services_pb"
62
-
63
- Google::Logging::V2::ConfigServiceV2::Stub.new(
64
- host, creds, timeout: timeout)
65
- end
67
+ @sinks ||= \
68
+ V2::ConfigServiceV2Api.new(
69
+ service_path: host,
70
+ channel: channel,
71
+ timeout: timeout,
72
+ client_config: client_config,
73
+ app_name: "gcloud-ruby",
74
+ app_version: Google::Cloud::Logging::VERSION)
66
75
  end
67
76
  attr_accessor :mocked_sinks
68
77
 
69
78
  def metrics
70
79
  return mocked_metrics if mocked_metrics
71
- @metrics ||= begin
72
- require "google/logging/v2/logging_metrics_services_pb"
73
-
74
- Google::Logging::V2::MetricsServiceV2::Stub.new(
75
- host, creds, timeout: timeout)
76
- end
80
+ @metrics ||= \
81
+ V2::MetricsServiceV2Api.new(
82
+ service_path: host,
83
+ channel: channel,
84
+ timeout: timeout,
85
+ client_config: client_config,
86
+ app_name: "gcloud-ruby",
87
+ app_version: Google::Cloud::Logging::VERSION)
77
88
  end
78
89
  attr_accessor :mocked_metrics
79
90
 
91
+ def insecure?
92
+ credentials == :this_channel_is_insecure
93
+ end
94
+
80
95
  def list_entries projects: nil, filter: nil, order: nil, token: nil,
81
96
  max: nil
82
- list_params = { project_ids: Array(projects || @project),
83
- filter: filter,
84
- order_by: order,
85
- page_token: token,
86
- page_size: max
87
- }.delete_if { |_, v| v.nil? }
88
97
 
89
- list_req = Google::Logging::V2::ListLogEntriesRequest.new(list_params)
98
+ project_ids = Array(projects || @project)
99
+ call_opts = default_options
100
+ if token
101
+ call_opts = Google::Gax::CallOptions.new(kwargs: default_headers,
102
+ page_token: token)
103
+ end
90
104
 
91
- execute { logging.list_log_entries list_req }
105
+ execute do
106
+ paged_enum = logging.list_log_entries project_ids,
107
+ filter: filter,
108
+ order_by: order,
109
+ page_size: max,
110
+ options: call_opts
111
+ paged_enum.page.response
112
+ end
92
113
  end
93
114
 
94
115
  def write_entries entries, log_name: nil, resource: nil, labels: nil
@@ -99,147 +120,124 @@ module Google
99
120
  resource = resource.to_grpc if resource
100
121
  labels = Hash[labels.map { |k, v| [String(k), String(v)] }] if labels
101
122
 
102
- write_params = { entries: entries,
103
- log_name: log_path(log_name),
104
- resource: resource, labels: labels
105
- }.delete_if { |_, v| v.nil? }
106
-
107
- write_req = Google::Logging::V2::WriteLogEntriesRequest.new(
108
- write_params)
109
-
110
- execute { logging.write_log_entries write_req }
123
+ execute do
124
+ logging.write_log_entries entries,
125
+ log_name: log_path(log_name),
126
+ resource: resource, labels: labels,
127
+ options: default_options
128
+ end
111
129
  end
112
130
 
113
131
  def delete_log name
114
- delete_req = Google::Logging::V2::DeleteLogRequest.new(
115
- log_name: log_path(name)
116
- )
117
-
118
- execute { logging.delete_log delete_req }
132
+ execute do
133
+ logging.delete_log log_path(name), options: default_options
134
+ end
119
135
  end
120
136
 
121
137
  def list_resource_descriptors token: nil, max: nil
122
- list_params = { page_token: token,
123
- page_size: max
124
- }.delete_if { |_, v| v.nil? }
125
-
126
- list_req = \
127
- Google::Logging::V2::ListMonitoredResourceDescriptorsRequest.new(
128
- list_params)
138
+ call_opts = default_options
139
+ if token
140
+ call_opts = Google::Gax::CallOptions.new(kwargs: default_headers,
141
+ page_token: token)
142
+ end
129
143
 
130
- execute { logging.list_monitored_resource_descriptors list_req }
144
+ execute do
145
+ logging.list_monitored_resource_descriptors \
146
+ page_size: max, options: call_opts
147
+ end
131
148
  end
132
149
 
133
150
  def list_sinks token: nil, max: nil
134
- list_params = { parent: project_path,
135
- page_token: token,
136
- page_size: max
137
- }.delete_if { |_, v| v.nil? }
138
-
139
- list_req = Google::Logging::V2::ListSinksRequest.new(list_params)
151
+ call_opts = default_options
152
+ if token
153
+ call_opts = Google::Gax::CallOptions.new(kwargs: default_headers,
154
+ page_token: token)
155
+ end
140
156
 
141
- execute { sinks.list_sinks list_req }
157
+ execute do
158
+ paged_enum = sinks.list_sinks \
159
+ project_path, page_size: max, options: call_opts
160
+ paged_enum.page.response
161
+ end
142
162
  end
143
163
 
144
164
  def create_sink name, destination, filter, version
145
- sink_params = {
146
- name: name, destination: destination,
147
- filter: filter, output_version_format: version
148
- }.delete_if { |_, v| v.nil? }
165
+ sink = Google::Logging::V2::LogSink.new({
166
+ name: name, destination: destination, filter: filter,
167
+ output_version_format: version }.delete_if { |_, v| v.nil? })
149
168
 
150
- create_req = Google::Logging::V2::CreateSinkRequest.new(
151
- parent: project_path,
152
- sink: Google::Logging::V2::LogSink.new(sink_params)
153
- )
154
-
155
- execute { sinks.create_sink create_req }
169
+ execute do
170
+ sinks.create_sink project_path, sink, options: default_options
171
+ end
156
172
  end
157
173
 
158
174
  def get_sink name
159
- get_req = Google::Logging::V2::GetSinkRequest.new(
160
- sink_name: sink_path(name)
161
- )
162
-
163
- execute { sinks.get_sink get_req }
175
+ execute { sinks.get_sink sink_path(name), options: default_options }
164
176
  end
165
177
 
166
178
  def update_sink name, destination, filter, version
167
- sink_params = {
168
- name: name, destination: destination,
169
- filter: filter, output_version_format: version
170
- }.delete_if { |_, v| v.nil? }
179
+ sink = Google::Logging::V2::LogSink.new({
180
+ name: name, destination: destination, filter: filter,
181
+ output_version_format: version }.delete_if { |_, v| v.nil? })
171
182
 
172
- update_req = Google::Logging::V2::UpdateSinkRequest.new(
173
- sink_name: sink_path(name),
174
- sink: Google::Logging::V2::LogSink.new(sink_params)
175
- )
176
-
177
- execute { sinks.update_sink update_req }
183
+ execute do
184
+ sinks.update_sink sink_path(name), sink, options: default_options
185
+ end
178
186
  end
179
187
 
180
188
  def delete_sink name
181
- delete_req = Google::Logging::V2::DeleteSinkRequest.new(
182
- sink_name: sink_path(name)
183
- )
184
-
185
- execute { sinks.delete_sink delete_req }
189
+ execute do
190
+ sinks.delete_sink sink_path(name), options: default_options
191
+ end
186
192
  end
187
193
 
188
194
  def list_metrics token: nil, max: nil
189
- list_params = { parent: project_path,
190
- page_token: token,
191
- page_size: max
192
- }.delete_if { |_, v| v.nil? }
193
-
194
- list_req = Google::Logging::V2::ListLogMetricsRequest.new(list_params)
195
+ call_opts = default_options
196
+ if token
197
+ call_opts = Google::Gax::CallOptions.new(kwargs: default_headers,
198
+ page_token: token)
199
+ end
195
200
 
196
- execute { metrics.list_log_metrics list_req }
201
+ execute do
202
+ paged_enum = metrics.list_log_metrics \
203
+ project_path, page_size: max, options: call_opts
204
+ paged_enum.page.response
205
+ end
197
206
  end
198
207
 
199
208
  def create_metric name, filter, description
200
- metric_params = {
201
- name: name,
202
- description: description,
203
- filter: filter
204
- }.delete_if { |_, v| v.nil? }
205
-
206
- create_req = Google::Logging::V2::CreateLogMetricRequest.new(
207
- parent: project_path,
208
- metric: Google::Logging::V2::LogMetric.new(metric_params)
209
- )
210
-
211
- execute { metrics.create_log_metric create_req }
209
+ metric = Google::Logging::V2::LogMetric.new({
210
+ name: name, description: description,
211
+ filter: filter }.delete_if { |_, v| v.nil? })
212
+
213
+ execute do
214
+ metrics.create_log_metric project_path, metric,
215
+ options: default_options
216
+ end
212
217
  end
213
218
 
214
219
  def get_metric name
215
- get_req = Google::Logging::V2::GetLogMetricRequest.new(
216
- metric_name: metric_path(name)
217
- )
218
-
219
- execute { metrics.get_log_metric get_req }
220
+ execute do
221
+ metrics.get_log_metric metric_path(name), options: default_options
222
+ end
220
223
  end
221
224
 
222
225
  def update_metric name, description, filter
223
- metric_params = {
224
- name: name,
225
- description: description,
226
- filter: filter
227
- }.delete_if { |_, v| v.nil? }
228
-
229
- update_req = Google::Logging::V2::UpdateLogMetricRequest.new(
230
- metric_name: metric_path(name),
231
- metric: Google::Logging::V2::LogMetric.new(metric_params)
232
- )
233
-
234
- execute { metrics.update_log_metric update_req }
226
+ metric = Google::Logging::V2::LogMetric.new({
227
+ name: name, description: description,
228
+ filter: filter }.delete_if { |_, v| v.nil? })
229
+
230
+ execute do
231
+ metrics.update_log_metric metric_path(name), metric,
232
+ options: default_options
233
+ end
235
234
  end
236
235
 
237
236
  def delete_metric name
238
- delete_req = Google::Logging::V2::DeleteLogMetricRequest.new(
239
- metric_name: metric_path(name)
240
- )
241
-
242
- execute { metrics.delete_log_metric delete_req }
237
+ execute do
238
+ metrics.delete_log_metric metric_path(name),
239
+ options: default_options
240
+ end
243
241
  end
244
242
 
245
243
  def inspect
@@ -269,12 +267,19 @@ module Google
269
267
  "#{project_path}/metrics/#{metric_name}"
270
268
  end
271
269
 
270
+ def default_headers
271
+ { "google-cloud-resource-prefix" => "projects/#{@project}" }
272
+ end
273
+
274
+ def default_options
275
+ Google::Gax::CallOptions.new kwargs: default_headers
276
+ end
277
+
272
278
  def execute
273
- Google::Cloud::Core::GrpcBackoff.new(retries: retries).execute do
274
- yield
275
- end
276
- rescue GRPC::BadStatus => e
277
- raise Google::Cloud::Error.from_error(e)
279
+ yield
280
+ rescue Google::Gax::GaxError => e
281
+ # GaxError wraps BadStatus, but exposes it as #cause
282
+ raise Google::Cloud::Error.from_error(e.cause)
278
283
  end
279
284
  end
280
285
  end