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,135 @@
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
+
16
+ module Google
17
+ module Cloud
18
+ module Logging
19
+ class Middleware
20
+ ##
21
+ # The Google::Cloud::Logging::Logger instance
22
+ attr_reader :logger
23
+
24
+ ##
25
+ # Create a new AppEngine logging Middleware.
26
+ #
27
+ # @param app Rack application
28
+ #
29
+ # @param [Google::Cloud::Logging::Logger] logger A logger to be used by
30
+ # this middleware. The middleware will be interacting with the logger
31
+ # to track Stackdriver request trace ID. It also properly sets
32
+ # env["rack.logger"] to this assigned logger for accessing.
33
+ #
34
+ # @return [Google::Cloud::Logging::Middleware] A new
35
+ # Google::Cloud::Logging::Middleware instance
36
+ #
37
+ def initialize app, logger: nil
38
+ @app = app
39
+ @logger = logger
40
+ end
41
+
42
+ ##
43
+ # Rack middleware entry point. In most Rack based frameworks, a request
44
+ # is served by one thread. So entry point, we associate the GCP request
45
+ # trace_id with the current thread's object_id in logger. All the logs
46
+ # written by logger beyond this point will carry this request's
47
+ # trace_id. Untrack the trace_id with this thread upon exiting.
48
+ #
49
+ # @param [Hash] env Rack environment hash
50
+ #
51
+ # @return The response from downstream Rack app
52
+ #
53
+ def call env
54
+ env["rack.logger"] = logger
55
+ trace_id = extract_trace_id(env)
56
+ logger.add_trace_id trace_id
57
+
58
+ begin
59
+ @app.call env
60
+ ensure
61
+ logger.delete_trace_id
62
+ end
63
+ end
64
+
65
+ ##
66
+ # Extract the trace_id from HTTP request header
67
+ # HTTP_X_CLOUD_TRACE_CONTEXT.
68
+ #
69
+ # @return [String] The trace_id or nil if trace_id is empty.
70
+ def extract_trace_id env
71
+ trace_context = env["HTTP_X_CLOUD_TRACE_CONTEXT"].to_s
72
+ return nil if trace_context.empty?
73
+ trace_context.sub(%r{/.*}, "")
74
+ end
75
+
76
+ ##
77
+ # @private Extract information from current environment and construct
78
+ # the correct monitoring resource types and labels.
79
+ #
80
+ # If running from GAE, return resource:
81
+ # {
82
+ # type: "gae_app", {
83
+ # module_id: [GAE module name],
84
+ # version_id: [GAE module version]
85
+ # }
86
+ # }
87
+ # If running from GKE, return resource:
88
+ # {
89
+ # type: "container", {
90
+ # cluster_name: [GKE cluster name],
91
+ # namespace_id: [GKE namespace_id]
92
+ # }
93
+ # }
94
+ # If running from GCE, return resource:
95
+ # {
96
+ # type: "gce_instance", {
97
+ # instance_id: [GCE VM instance id],
98
+ # zone: [GCE vm group zone]
99
+ # }
100
+ # }
101
+ # Otherwise default to { type: "global" }, which means not associated
102
+ # with GCP.
103
+ #
104
+ # Reference https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/MonitoredResource
105
+ # for a full list of monitoring resources
106
+ #
107
+ # @return [Google::Cloud::Logging::Resource] An Resource object with
108
+ # correct type and labels
109
+ def self.build_monitoring_resource
110
+ type, labels =
111
+ if Core::Environment.gae?
112
+ ["gae_app", {
113
+ module_id: Core::Environment.gae_module_id,
114
+ version_id: Core::Environment.gae_module_version }]
115
+ elsif Core::Environment.gke?
116
+ ["container", {
117
+ cluster_name: Core::Environment.gke_cluster_name,
118
+ namespace_id: Core::Environment.gke_namespace_id || "default" }]
119
+ elsif Core::Environment.gce?
120
+ ["gce_instance", {
121
+ instance_id: Core::Environment.instance_id,
122
+ zone: Core::Environment.instance_zone }]
123
+ else
124
+ ["global", {}]
125
+ end
126
+
127
+ Google::Cloud::Logging::Resource.new.tap do |r|
128
+ r.type = type
129
+ r.labels = labels
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -14,14 +14,16 @@
14
14
 
15
15
 
16
16
  require "google/cloud/errors"
17
- require "google/cloud/core/gce"
17
+ require "google/cloud/core/environment"
18
18
  require "google/cloud/logging/service"
19
19
  require "google/cloud/logging/credentials"
20
20
  require "google/cloud/logging/entry"
21
21
  require "google/cloud/logging/resource_descriptor"
22
22
  require "google/cloud/logging/sink"
23
23
  require "google/cloud/logging/metric"
24
+ require "google/cloud/logging/async_writer"
24
25
  require "google/cloud/logging/logger"
26
+ require "google/cloud/logging/middleware"
25
27
 
26
28
  module Google
27
29
  module Cloud
@@ -37,10 +39,9 @@ module Google
37
39
  # {Google::Cloud#logging}.
38
40
  #
39
41
  # @example
40
- # require "google/cloud"
42
+ # require "google/cloud/logging"
41
43
  #
42
- # gcloud = Google::Cloud.new
43
- # logging = gcloud.logging
44
+ # logging = Google::Cloud::Logging.new
44
45
  # entries = logging.entries
45
46
  #
46
47
  # See Google::Cloud#logging
@@ -61,10 +62,12 @@ module Google
61
62
  # @return [String] the Google Cloud project ID
62
63
  #
63
64
  # @example
64
- # require "google/cloud"
65
+ # require "google/cloud/logging"
65
66
  #
66
- # gcloud = Google::Cloud.new "my-project", "/path/to/keyfile.json"
67
- # logging = gcloud.logging
67
+ # logging = Google::Cloud::Logging.new(
68
+ # project: "my-project",
69
+ # keyfile: "/path/to/keyfile.json"
70
+ # )
68
71
  #
69
72
  # logging.project #=> "my-project"
70
73
  #
@@ -78,7 +81,7 @@ module Google
78
81
  ENV["LOGGING_PROJECT"] ||
79
82
  ENV["GOOGLE_CLOUD_PROJECT"] ||
80
83
  ENV["GCLOUD_PROJECT"] ||
81
- Google::Cloud::Core::GCE.project_id
84
+ Google::Cloud::Core::Environment.project_id
82
85
  end
83
86
 
84
87
  ##
@@ -104,40 +107,36 @@ module Google
104
107
  # {Google::Cloud::Logging::Entry::List})
105
108
  #
106
109
  # @example
107
- # require "google/cloud"
110
+ # require "google/cloud/logging"
108
111
  #
109
- # gcloud = Google::Cloud.new
110
- # logging = gcloud.logging
112
+ # logging = Google::Cloud::Logging.new
111
113
  # entries = logging.entries
112
114
  # entries.each do |e|
113
115
  # puts "[#{e.timestamp}] #{e.log_name} #{e.payload.inspect}"
114
116
  # end
115
117
  #
116
118
  # @example You can use a filter to narrow results to a single log.
117
- # require "google/cloud"
119
+ # require "google/cloud/logging"
118
120
  #
119
- # gcloud = Google::Cloud.new
120
- # logging = gcloud.logging
121
+ # logging = Google::Cloud::Logging.new
121
122
  # entries = logging.entries filter: "log:syslog"
122
123
  # entries.each do |e|
123
124
  # puts "[#{e.timestamp}] #{e.payload.inspect}"
124
125
  # end
125
126
  #
126
127
  # @example You can also order the results by timestamp.
127
- # require "google/cloud"
128
+ # require "google/cloud/logging"
128
129
  #
129
- # gcloud = Google::Cloud.new
130
- # logging = gcloud.logging
130
+ # logging = Google::Cloud::Logging.new
131
131
  # entries = logging.entries order: "timestamp desc"
132
132
  # entries.each do |e|
133
133
  # puts "[#{e.timestamp}] #{e.log_name} #{e.payload.inspect}"
134
134
  # end
135
135
  #
136
136
  # @example Retrieve all log entries: (See {Entry::List#all})
137
- # require "google/cloud"
137
+ # require "google/cloud/logging"
138
138
  #
139
- # gcloud = Google::Cloud.new
140
- # logging = gcloud.logging
139
+ # logging = Google::Cloud::Logging.new
141
140
  # entries = logging.entries
142
141
  #
143
142
  # entries.all do |e|
@@ -184,10 +183,9 @@ module Google
184
183
  # @return [Google::Cloud::Logging::Entry] a new Entry instance
185
184
  #
186
185
  # @example
187
- # require "google/cloud"
186
+ # require "google/cloud/logging"
188
187
  #
189
- # gcloud = Google::Cloud.new
190
- # logging = gcloud.logging
188
+ # logging = Google::Cloud::Logging.new
191
189
  #
192
190
  # entry = logging.entry severity: :INFO, payload: "Job started."
193
191
  #
@@ -232,10 +230,9 @@ module Google
232
230
  # @return [Boolean] Returns `true` if the entries were written.
233
231
  #
234
232
  # @example
235
- # require "google/cloud"
233
+ # require "google/cloud/logging"
236
234
  #
237
- # gcloud = Google::Cloud.new
238
- # logging = gcloud.logging
235
+ # logging = Google::Cloud::Logging.new
239
236
  #
240
237
  # entry = logging.entry payload: "Job started.",
241
238
  # log_name: "my_app_log"
@@ -246,10 +243,9 @@ module Google
246
243
  # logging.write_entries entry
247
244
  #
248
245
  # @example Optionally pass log name, resource, and labels for entries.
249
- # require "google/cloud"
246
+ # require "google/cloud/logging"
250
247
  #
251
- # gcloud = Google::Cloud.new
252
- # logging = gcloud.logging
248
+ # logging = Google::Cloud::Logging.new
253
249
  #
254
250
  # entry1 = logging.entry payload: "Job started."
255
251
  # entry2 = logging.entry payload: "Job completed."
@@ -272,10 +268,83 @@ module Google
272
268
  true
273
269
  end
274
270
 
271
+ ##
272
+ # Creates an object that batches and transmits log entries
273
+ # asynchronously.
274
+ #
275
+ # Use this object to transmit log entries efficiently. It keeps a queue
276
+ # of log entries, and runs a background thread that transmits them to
277
+ # the logging service in batches. Generally, adding to the queue will
278
+ # not block.
279
+ #
280
+ # This object is thread-safe; it may accept write requests from
281
+ # multiple threads simultaneously, and will serialize them when
282
+ # executing in the background thread.
283
+ #
284
+ # @param [Integer] max_queue_size The maximum number of log entries
285
+ # that may be queued before write requests will begin to block.
286
+ # This provides back pressure in case the transmitting thread cannot
287
+ # keep up with requests.
288
+ #
289
+ # @example
290
+ # require "google/cloud/logging"
291
+ #
292
+ # logging = Google::Cloud::Logging.new
293
+ #
294
+ # async = logging.async_writer
295
+ #
296
+ # entry1 = logging.entry payload: "Job started."
297
+ # entry2 = logging.entry payload: "Job completed."
298
+ #
299
+ # labels = { job_size: "large", job_code: "red" }
300
+ # resource = logging.resource "gae_app",
301
+ # "module_id" => "1",
302
+ # "version_id" => "20150925t173233"
303
+ #
304
+ # async.write_entries [entry1, entry2],
305
+ # log_name: "my_app_log",
306
+ # resource: resource,
307
+ # labels: labels
308
+ #
309
+ def async_writer max_queue_size: AsyncWriter::DEFAULT_MAX_QUEUE_SIZE
310
+ AsyncWriter.new self, max_queue_size
311
+ end
312
+
313
+ ##
314
+ # Returns a shared AsyncWriter for this Project. If this method is
315
+ # called multiple times, it will return the same object.
316
+ #
317
+ # @example
318
+ # require "google/cloud/logging"
319
+ #
320
+ # logging = Google::Cloud::Logging.new
321
+ #
322
+ # async = logging.shared_async_writer
323
+ #
324
+ # entry1 = logging.entry payload: "Job started."
325
+ # entry2 = logging.entry payload: "Job completed."
326
+ #
327
+ # labels = { job_size: "large", job_code: "red" }
328
+ # resource = logging.resource "gae_app",
329
+ # "module_id" => "1",
330
+ # "version_id" => "20150925t173233"
331
+ #
332
+ # async.write_entries [entry1, entry2],
333
+ # log_name: "my_app_log",
334
+ # resource: resource,
335
+ # labels: labels
336
+ #
337
+ def shared_async_writer
338
+ @shared_async_writer ||= async_writer
339
+ end
340
+
275
341
  ##
276
342
  # Creates a logger instance that is API-compatible with Ruby's standard
277
343
  # library [Logger](http://ruby-doc.org/stdlib/libdoc/logger/rdoc).
278
344
  #
345
+ # The logger will create a new AsyncWriter object to transmit log
346
+ # entries on a background thread.
347
+ #
279
348
  # @param [String] log_name A log resource name to be associated with the
280
349
  # written log entries.
281
350
  # @param [Google::Cloud::Logging::Resource] resource The monitored
@@ -287,10 +356,9 @@ module Google
287
356
  # used in place of a ruby standard library logger object.
288
357
  #
289
358
  # @example
290
- # require "google/cloud"
359
+ # require "google/cloud/logging"
291
360
  #
292
- # gcloud = Google::Cloud.new
293
- # logging = gcloud.logging
361
+ # logging = Google::Cloud::Logging.new
294
362
  #
295
363
  # resource = logging.resource "gae_app",
296
364
  # module_id: "1",
@@ -300,7 +368,7 @@ module Google
300
368
  # logger.info "Job started."
301
369
  #
302
370
  def logger log_name, resource, labels = {}
303
- Logger.new self, log_name, resource, labels
371
+ Logger.new shared_async_writer, log_name, resource, labels
304
372
  end
305
373
 
306
374
  ##
@@ -317,10 +385,9 @@ module Google
317
385
  # were deleted.
318
386
  #
319
387
  # @example
320
- # require "google/cloud"
388
+ # require "google/cloud/logging"
321
389
  #
322
- # gcloud = Google::Cloud.new
323
- # logging = gcloud.logging
390
+ # logging = Google::Cloud::Logging.new
324
391
  # logging.delete_log "my_app_log"
325
392
  #
326
393
  def delete_log name
@@ -344,10 +411,9 @@ module Google
344
411
  # {Google::Cloud::Logging::ResourceDescriptor::List})
345
412
  #
346
413
  # @example
347
- # require "google/cloud"
414
+ # require "google/cloud/logging"
348
415
  #
349
- # gcloud = Google::Cloud.new
350
- # logging = gcloud.logging
416
+ # logging = Google::Cloud::Logging.new
351
417
  # resource_descriptors = logging.resource_descriptors
352
418
  # resource_descriptors.each do |rd|
353
419
  # label_keys = rd.labels.map(&:key).join(", ")
@@ -355,10 +421,9 @@ module Google
355
421
  # end
356
422
  #
357
423
  # @example Pagination:
358
- # require "google/cloud"
424
+ # require "google/cloud/logging"
359
425
  #
360
- # gcloud = Google::Cloud.new
361
- # logging = gcloud.logging
426
+ # logging = Google::Cloud::Logging.new
362
427
  # resource_descriptors = logging.resource_descriptors
363
428
  #
364
429
  # resource_descriptors.all do |rd|
@@ -375,13 +440,17 @@ module Google
375
440
  ##
376
441
  # Creates a new monitored resource instance.
377
442
  #
443
+ # @param [String] type The type of resource, as represented by a
444
+ # {ResourceDescriptor}.
445
+ # @param [Hash] labels A set of labels that can be used to describe
446
+ # instances of this monitored resource type.
447
+ #
378
448
  # @return [Google::Cloud::Logging::Resource]
379
449
  #
380
450
  # @example
381
- # require "google/cloud"
451
+ # require "google/cloud/logging"
382
452
  #
383
- # gcloud = Google::Cloud.new
384
- # logging = gcloud.logging
453
+ # logging = Google::Cloud::Logging.new
385
454
  #
386
455
  # resource = logging.resource "gae_app",
387
456
  # "module_id" => "1",
@@ -406,20 +475,18 @@ module Google
406
475
  # {Google::Cloud::Logging::Sink::List})
407
476
  #
408
477
  # @example
409
- # require "google/cloud"
478
+ # require "google/cloud/logging"
410
479
  #
411
- # gcloud = Google::Cloud.new
412
- # logging = gcloud.logging
480
+ # logging = Google::Cloud::Logging.new
413
481
  # sinks = logging.sinks
414
482
  # sinks.each do |s|
415
483
  # puts "#{s.name}: #{s.filter} -> #{s.destination}"
416
484
  # end
417
485
  #
418
486
  # @example Retrieve all sinks: (See {Sink::List#all})
419
- # require "google/cloud"
487
+ # require "google/cloud/logging"
420
488
  #
421
- # gcloud = Google::Cloud.new
422
- # logging = gcloud.logging
489
+ # logging = Google::Cloud::Logging.new
423
490
  # sinks = logging.sinks
424
491
  #
425
492
  # sinks.all do |s|
@@ -477,11 +544,9 @@ module Google
477
544
  # @return [Google::Cloud::Logging::Sink] a project sink
478
545
  #
479
546
  # @example
480
- # require "google/cloud"
547
+ # require "google/cloud/storage"
481
548
  #
482
- # gcloud = Google::Cloud.new
483
- # logging = gcloud.logging
484
- # storage = gcloud.storage
549
+ # storage = Google::Cloud::Storage.new
485
550
  #
486
551
  # bucket = storage.create_bucket "my-logs-bucket"
487
552
  #
@@ -489,6 +554,10 @@ module Google
489
554
  # email = "cloud-logs@google.com"
490
555
  # bucket.acl.add_owner "group-#{email}"
491
556
  #
557
+ # require "google/cloud/logging"
558
+ #
559
+ # logging = Google::Cloud::Logging.new
560
+ #
492
561
  # sink = logging.create_sink "my-sink",
493
562
  # "storage.googleapis.com/#{bucket.id}"
494
563
  #
@@ -509,17 +578,15 @@ module Google
509
578
  # does not exist.
510
579
  #
511
580
  # @example
512
- # require "google/cloud"
581
+ # require "google/cloud/logging"
513
582
  #
514
- # gcloud = Google::Cloud.new
515
- # logging = gcloud.logging
583
+ # logging = Google::Cloud::Logging.new
516
584
  # sink = logging.sink "existing-sink"
517
585
  #
518
586
  # @example By default `nil` will be returned if the sink does not exist.
519
- # require "google/cloud"
587
+ # require "google/cloud/logging"
520
588
  #
521
- # gcloud = Google::Cloud.new
522
- # logging = gcloud.logging
589
+ # logging = Google::Cloud::Logging.new
523
590
  # sink = logging.sink "non-existing-sink" #=> nil
524
591
  #
525
592
  def sink sink_name
@@ -543,20 +610,18 @@ module Google
543
610
  # {Google::Cloud::Logging::Metric::List})
544
611
  #
545
612
  # @example
546
- # require "google/cloud"
613
+ # require "google/cloud/logging"
547
614
  #
548
- # gcloud = Google::Cloud.new
549
- # logging = gcloud.logging
615
+ # logging = Google::Cloud::Logging.new
550
616
  # metrics = logging.metrics
551
617
  # metrics.each do |m|
552
618
  # puts "#{m.name}: #{m.filter}"
553
619
  # end
554
620
  #
555
621
  # @example Retrieve all metrics: (See {Metric::List#all})
556
- # require "google/cloud"
622
+ # require "google/cloud/logging"
557
623
  #
558
- # gcloud = Google::Cloud.new
559
- # logging = gcloud.logging
624
+ # logging = Google::Cloud::Logging.new
560
625
  # metrics = logging.metrics
561
626
  #
562
627
  # metrics.all do |m|
@@ -591,10 +656,9 @@ module Google
591
656
  # @return [Google::Cloud::Logging::Metric]
592
657
  #
593
658
  # @example
594
- # require "google/cloud"
659
+ # require "google/cloud/logging"
595
660
  #
596
- # gcloud = Google::Cloud.new
597
- # logging = gcloud.logging
661
+ # logging = Google::Cloud::Logging.new
598
662
  # metric = logging.create_metric "errors", "severity>=ERROR"
599
663
  #
600
664
  def create_metric name, filter, description: nil
@@ -613,17 +677,15 @@ module Google
613
677
  # does not exist.
614
678
  #
615
679
  # @example
616
- # require "google/cloud"
680
+ # require "google/cloud/logging"
617
681
  #
618
- # gcloud = Google::Cloud.new
619
- # logging = gcloud.logging
682
+ # logging = Google::Cloud::Logging.new
620
683
  # metric = logging.metric "existing_metric"
621
684
  #
622
685
  # @example By default `nil` will be returned if metric does not exist.
623
- # require "google/cloud"
686
+ # require "google/cloud/logging"
624
687
  #
625
- # gcloud = Google::Cloud.new
626
- # logging = gcloud.logging
688
+ # logging = Google::Cloud::Logging.new
627
689
  # metric = logging.metric "non_existing_metric" #=> nil
628
690
  #
629
691
  def metric name