google-cloud-logging 2.0.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 +7 -0
- data/.yardopts +18 -0
- data/AUTHENTICATION.md +178 -0
- data/CHANGELOG.md +407 -0
- data/CODE_OF_CONDUCT.md +40 -0
- data/CONTRIBUTING.md +188 -0
- data/INSTRUMENTATION.md +71 -0
- data/LICENSE +201 -0
- data/LOGGING.md +32 -0
- data/OVERVIEW.md +321 -0
- data/TROUBLESHOOTING.md +31 -0
- data/lib/google-cloud-logging.rb +161 -0
- data/lib/google/cloud/logging.rb +188 -0
- data/lib/google/cloud/logging/async_writer.rb +513 -0
- data/lib/google/cloud/logging/convert.rb +70 -0
- data/lib/google/cloud/logging/credentials.rb +44 -0
- data/lib/google/cloud/logging/entry.rb +528 -0
- data/lib/google/cloud/logging/entry/http_request.rb +167 -0
- data/lib/google/cloud/logging/entry/list.rb +178 -0
- data/lib/google/cloud/logging/entry/operation.rb +91 -0
- data/lib/google/cloud/logging/entry/source_location.rb +85 -0
- data/lib/google/cloud/logging/errors.rb +101 -0
- data/lib/google/cloud/logging/log/list.rb +156 -0
- data/lib/google/cloud/logging/logger.rb +633 -0
- data/lib/google/cloud/logging/metric.rb +168 -0
- data/lib/google/cloud/logging/metric/list.rb +170 -0
- data/lib/google/cloud/logging/middleware.rb +307 -0
- data/lib/google/cloud/logging/project.rb +838 -0
- data/lib/google/cloud/logging/rails.rb +232 -0
- data/lib/google/cloud/logging/resource.rb +85 -0
- data/lib/google/cloud/logging/resource_descriptor.rb +137 -0
- data/lib/google/cloud/logging/resource_descriptor/list.rb +175 -0
- data/lib/google/cloud/logging/service.rb +239 -0
- data/lib/google/cloud/logging/sink.rb +315 -0
- data/lib/google/cloud/logging/sink/list.rb +168 -0
- data/lib/google/cloud/logging/version.rb +22 -0
- metadata +304 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
# Copyright 2018 Google LLC
|
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
|
+
# https://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
|
+
require "google/cloud/errors"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Logging
|
21
|
+
##
|
22
|
+
# # AsyncWriterError
|
23
|
+
#
|
24
|
+
# Used to indicate a problem preventing {AsyncWriter} from asynchronously
|
25
|
+
# calling the API. This can occur when the {AsyncWriter} has too few
|
26
|
+
# resources allocated for the amount of usage.
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# require "google/cloud/logging"
|
30
|
+
# require "google/cloud/error_reporting"
|
31
|
+
#
|
32
|
+
# logging = Google::Cloud::Logging.new
|
33
|
+
#
|
34
|
+
# resource = logging.resource "gae_app",
|
35
|
+
# module_id: "1",
|
36
|
+
# version_id: "20150925t173233"
|
37
|
+
#
|
38
|
+
# async = logging.async_writer
|
39
|
+
#
|
40
|
+
# # Register to be notified when unhandled errors occur.
|
41
|
+
# async.on_error do |error|
|
42
|
+
# # error can be a AsyncWriterError, with entries
|
43
|
+
# Google::Cloud::ErrorReporting.report error
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# logger = async.logger "my_app_log", resource, env: :production
|
47
|
+
# logger.info "Job started."
|
48
|
+
#
|
49
|
+
class AsyncWriterError < Google::Cloud::Error
|
50
|
+
# @!attribute [r] count
|
51
|
+
# @return [Array<Google::Cloud::Logging::Entry>] entries The entry
|
52
|
+
# objects that were not written to the API due to the error.
|
53
|
+
attr_reader :entries
|
54
|
+
|
55
|
+
def initialize message, entries = nil
|
56
|
+
super message
|
57
|
+
@entries = entries if entries
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# # AsyncWriteEntriesError
|
63
|
+
#
|
64
|
+
# Used to indicate a problem when {AsyncWriter} writes log entries to the
|
65
|
+
# API. This can occur when the API returns an error.
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# require "google/cloud/logging"
|
69
|
+
# require "google/cloud/error_reporting"
|
70
|
+
#
|
71
|
+
# logging = Google::Cloud::Logging.new
|
72
|
+
#
|
73
|
+
# resource = logging.resource "gae_app",
|
74
|
+
# module_id: "1",
|
75
|
+
# version_id: "20150925t173233"
|
76
|
+
#
|
77
|
+
# async = logging.async_writer
|
78
|
+
#
|
79
|
+
# # Register to be notified when unhandled errors occur.
|
80
|
+
# async.on_error do |error|
|
81
|
+
# # error can be a AsyncWriteEntriesError, with entries
|
82
|
+
# Google::Cloud::ErrorReporting.report error
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# logger = async.logger "my_app_log", resource, env: :production
|
86
|
+
# logger.info "Job started."
|
87
|
+
#
|
88
|
+
class AsyncWriteEntriesError < Google::Cloud::Error
|
89
|
+
# @!attribute [r] count
|
90
|
+
# @return [Array<Google::Cloud::Logging::Entry>] entries The entry
|
91
|
+
# objects that were not written to the API due to the error.
|
92
|
+
attr_reader :entries
|
93
|
+
|
94
|
+
def initialize message, entries = nil
|
95
|
+
super message
|
96
|
+
@entries = entries if entries
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# Copyright 2017 Google LLC
|
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
|
+
# https://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
|
+
require "delegate"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Logging
|
21
|
+
class Log
|
22
|
+
##
|
23
|
+
# Log::List is a special case Array with additional values.
|
24
|
+
class List < DelegateClass(::Array)
|
25
|
+
##
|
26
|
+
# If not empty, indicates that there are more records that match
|
27
|
+
# the request and this value should be passed to continue.
|
28
|
+
attr_accessor :token
|
29
|
+
|
30
|
+
##
|
31
|
+
# @private Create a new Log::List with an array of log names.
|
32
|
+
def initialize arr = []
|
33
|
+
super arr
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Whether there is a next page of logs.
|
38
|
+
#
|
39
|
+
# @return [Boolean]
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# require "google/cloud/logging"
|
43
|
+
#
|
44
|
+
# logging = Google::Cloud::Logging.new
|
45
|
+
#
|
46
|
+
# logs = logging.logs
|
47
|
+
# if logs.next?
|
48
|
+
# next_logs = logs.next
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
def next?
|
52
|
+
!token.nil?
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Retrieve the next page of logs.
|
57
|
+
#
|
58
|
+
# @return [Log::List]
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# require "google/cloud/logging"
|
62
|
+
#
|
63
|
+
# logging = Google::Cloud::Logging.new
|
64
|
+
#
|
65
|
+
# logs = logging.logs
|
66
|
+
# if logs.next?
|
67
|
+
# next_logs = logs.next
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
def next
|
71
|
+
return nil unless next?
|
72
|
+
ensure_service!
|
73
|
+
grpc = @service.list_logs token: token, resource: @resource,
|
74
|
+
max: @max
|
75
|
+
self.class.from_grpc grpc, @service, resource: @resource,
|
76
|
+
max: @max
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Retrieves remaining results by repeatedly invoking {#next} until
|
81
|
+
# {#next?} returns `false`. Calls the given block once for each
|
82
|
+
# result, which is passed as the argument to the block.
|
83
|
+
#
|
84
|
+
# An Enumerator is returned if no block is given.
|
85
|
+
#
|
86
|
+
# This method will make repeated API calls until all remaining results
|
87
|
+
# are retrieved. (Unlike `#each`, for example, which merely iterates
|
88
|
+
# over the results returned by a single API call.) Use with caution.
|
89
|
+
#
|
90
|
+
# @param [Integer] request_limit The upper limit of API requests to
|
91
|
+
# make to load all log names. Default is no limit.
|
92
|
+
# @yield [log] The block for accessing each log name.
|
93
|
+
# @yieldparam [String] log The log name.
|
94
|
+
#
|
95
|
+
# @return [Enumerator]
|
96
|
+
#
|
97
|
+
# @example Iterating each log name by passing a block:
|
98
|
+
# require "google/cloud/logging"
|
99
|
+
#
|
100
|
+
# logging = Google::Cloud::Logging.new
|
101
|
+
# logs = logging.logs
|
102
|
+
#
|
103
|
+
# logs.all { |l| puts l }
|
104
|
+
#
|
105
|
+
# @example Limit the number of API calls made:
|
106
|
+
# require "google/cloud/logging"
|
107
|
+
#
|
108
|
+
# logging = Google::Cloud::Logging.new
|
109
|
+
# logs = logging.logs
|
110
|
+
#
|
111
|
+
# logs.all(request_limit: 10) { |l| puts l }
|
112
|
+
#
|
113
|
+
def all request_limit: nil
|
114
|
+
request_limit = request_limit.to_i if request_limit
|
115
|
+
unless block_given?
|
116
|
+
return enum_for :all, request_limit: request_limit
|
117
|
+
end
|
118
|
+
results = self
|
119
|
+
loop do
|
120
|
+
results.each { |r| yield r }
|
121
|
+
if request_limit
|
122
|
+
request_limit -= 1
|
123
|
+
break if request_limit < 0
|
124
|
+
end
|
125
|
+
break unless results.next?
|
126
|
+
results = results.next
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# @private New Log::List from a
|
132
|
+
# Google::Cloud::Logging::V2::ListLogsResponse object.
|
133
|
+
def self.from_grpc grpc_list, service, resource: nil, max: nil
|
134
|
+
logs = new Array(grpc_list.log_names)
|
135
|
+
token = grpc_list.next_page_token
|
136
|
+
token = nil if token == "".freeze
|
137
|
+
logs.instance_variable_set :@token, token
|
138
|
+
logs.instance_variable_set :@service, service
|
139
|
+
logs.instance_variable_set :@resource, resource
|
140
|
+
logs.instance_variable_set :@max, max
|
141
|
+
logs
|
142
|
+
end
|
143
|
+
|
144
|
+
protected
|
145
|
+
|
146
|
+
##
|
147
|
+
# @private Raise an error unless an active connection to the service
|
148
|
+
# is available.
|
149
|
+
def ensure_service!
|
150
|
+
raise "Must have active connection to service" unless @service
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,633 @@
|
|
1
|
+
# Copyright 2016 Google LLC
|
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
|
+
# https://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
|
+
require "logger"
|
17
|
+
require "concurrent"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module Logging
|
22
|
+
##
|
23
|
+
# # Logger
|
24
|
+
#
|
25
|
+
# An API-compatible replacement for ruby's Logger that logs to the
|
26
|
+
# Stackdriver Logging Service.
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# require "google/cloud/logging"
|
30
|
+
#
|
31
|
+
# logging = Google::Cloud::Logging.new
|
32
|
+
#
|
33
|
+
# resource = logging.resource "gae_app",
|
34
|
+
# module_id: "1",
|
35
|
+
# version_id: "20150925t173233"
|
36
|
+
#
|
37
|
+
# logger = logging.logger "my_app_log", resource, env: :production
|
38
|
+
# logger.info "Job started."
|
39
|
+
#
|
40
|
+
# @example Provide a hash to write a JSON payload to the log:
|
41
|
+
# require "google/cloud/logging"
|
42
|
+
#
|
43
|
+
# logging = Google::Cloud::Logging.new
|
44
|
+
#
|
45
|
+
# resource = logging.resource "gae_app",
|
46
|
+
# module_id: "1",
|
47
|
+
# version_id: "20150925t173233"
|
48
|
+
#
|
49
|
+
# logger = logging.logger "my_app_log", resource, env: :production
|
50
|
+
#
|
51
|
+
# payload = { "stats" => { "a" => 8, "b" => 12.5} }
|
52
|
+
# logger.info payload
|
53
|
+
#
|
54
|
+
class Logger
|
55
|
+
##
|
56
|
+
# A RequestInfo represents data about the request being handled by the
|
57
|
+
# current thread. It is used to configure logs coming from that thread.
|
58
|
+
#
|
59
|
+
# The trace_id is a String that controls the trace ID sent with the log
|
60
|
+
# entry. If it is nil, no trace ID is sent.
|
61
|
+
#
|
62
|
+
# The log_name is a String that controls the name of the Stackdriver
|
63
|
+
# log to write to. If it is nil, the default log_name for this Logger
|
64
|
+
# is used.
|
65
|
+
RequestInfo = ::Struct.new :trace_id, :log_name, :env, :trace_sampled
|
66
|
+
|
67
|
+
##
|
68
|
+
# The Google Cloud writer object that calls to `#write_entries` are made
|
69
|
+
# on. Either an AsyncWriter or Project object.
|
70
|
+
attr_reader :writer
|
71
|
+
|
72
|
+
##
|
73
|
+
# The Google Cloud log_name to write the log entry with.
|
74
|
+
attr_reader :log_name
|
75
|
+
alias progname log_name
|
76
|
+
|
77
|
+
##
|
78
|
+
# The Google Cloud resource to write the log entry with.
|
79
|
+
attr_reader :resource
|
80
|
+
|
81
|
+
##
|
82
|
+
# The Google Cloud labels to write the log entry with.
|
83
|
+
attr_reader :labels
|
84
|
+
|
85
|
+
##
|
86
|
+
# The logging severity threshold (e.g. `Logger::INFO`)
|
87
|
+
attr_reader :level
|
88
|
+
alias sev_threshold level
|
89
|
+
alias local_level level
|
90
|
+
|
91
|
+
##
|
92
|
+
# Boolean flag that indicates whether this logger can be silenced or
|
93
|
+
# not.
|
94
|
+
attr_accessor :silencer
|
95
|
+
|
96
|
+
##
|
97
|
+
# This logger does not use a formatter, but it provides a default
|
98
|
+
# Logger::Formatter for API compatibility with the standard Logger.
|
99
|
+
attr_accessor :formatter
|
100
|
+
|
101
|
+
##
|
102
|
+
# This logger does not use a formatter, but it implements this
|
103
|
+
# attribute for API compatibility with the standard Logger.
|
104
|
+
attr_accessor :datetime_format
|
105
|
+
|
106
|
+
##
|
107
|
+
# The project ID this logger is sending data to. If set, this value is
|
108
|
+
# used to set the trace field of log entries.
|
109
|
+
attr_accessor :project
|
110
|
+
|
111
|
+
##
|
112
|
+
# This logger treats progname as an alias for log_name.
|
113
|
+
def progname= name
|
114
|
+
@log_name = name
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# A Hash of Thread IDs to Stackdriver request trace ID. The
|
119
|
+
# Stackdriver trace ID is a shared request identifier across all
|
120
|
+
# Stackdriver services.
|
121
|
+
#
|
122
|
+
# This method is deprecated and returns a Hash containing only the
|
123
|
+
# current Thread ID/trace_id now.
|
124
|
+
#
|
125
|
+
# @deprecated Use request_info
|
126
|
+
#
|
127
|
+
def trace_ids
|
128
|
+
current_request_info = request_info
|
129
|
+
return {} if current_request_info.nil?
|
130
|
+
{ current_thread_id => current_request_info.trace_id }
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# Create a new Logger instance.
|
135
|
+
#
|
136
|
+
# @param [#write_entries] writer The object that will transmit log
|
137
|
+
# entries. Generally, to create a logger that blocks on transmitting
|
138
|
+
# log entries, pass the Project; otherwise, to create a logger that
|
139
|
+
# transmits log entries in the background, pass an AsyncWriter. You
|
140
|
+
# may also pass any other object that responds to `#write_entries`.
|
141
|
+
# @param [String] log_name A log resource name to be associated with the
|
142
|
+
# written log entries.
|
143
|
+
# @param [Google::Cloud::Logging::Resource] resource The monitored
|
144
|
+
# resource to be associated with written log entries.
|
145
|
+
# @param [Hash] labels A set of user-defined data to be associated with
|
146
|
+
# written log entries.
|
147
|
+
#
|
148
|
+
# @return [Google::Cloud::Logging::Logger] a Logger object that can be
|
149
|
+
# used in place of a ruby standard library logger object.
|
150
|
+
#
|
151
|
+
# @example
|
152
|
+
# require "google/cloud/logging"
|
153
|
+
#
|
154
|
+
# logging = Google::Cloud::Logging.new
|
155
|
+
#
|
156
|
+
# writer = logging.async_writer max_queue_size: 1000
|
157
|
+
#
|
158
|
+
# resource = logging.resource "gae_app", labels: {
|
159
|
+
# "module_id" => "1",
|
160
|
+
# "version_id" => "20150925t173233"
|
161
|
+
# }
|
162
|
+
#
|
163
|
+
# logger = Google::Cloud::Logging::Logger.new writer,
|
164
|
+
# "my_app_log",
|
165
|
+
# resource,
|
166
|
+
# env: :production
|
167
|
+
# logger.info "Job started."
|
168
|
+
#
|
169
|
+
def initialize writer, log_name, resource, labels = nil
|
170
|
+
@writer = writer
|
171
|
+
@log_name = log_name
|
172
|
+
@resource = resource
|
173
|
+
@labels = labels || {}
|
174
|
+
@level = 0 # DEBUG is the default behavior
|
175
|
+
@request_info_var = Concurrent::ThreadLocalVar.new
|
176
|
+
@closed = false
|
177
|
+
# Unused, but present for API compatibility
|
178
|
+
@formatter = ::Logger::Formatter.new
|
179
|
+
@datetime_format = ""
|
180
|
+
@silencer = true
|
181
|
+
|
182
|
+
# The writer is usually a Project or AsyncWriter.
|
183
|
+
logging = @writer.respond_to?(:logging) ? @writer.logging : @writer
|
184
|
+
@project = logging.project if logging.respond_to? :project
|
185
|
+
end
|
186
|
+
|
187
|
+
##
|
188
|
+
# Log a `DEBUG` entry.
|
189
|
+
#
|
190
|
+
# @param [String, Hash] message The log entry payload, represented as
|
191
|
+
# either a string, a hash (JSON), or a hash (protocol buffer).
|
192
|
+
# @yield Evaluates to the message to log. This is not evaluated unless
|
193
|
+
# the logger's level is sufficient to log the message. This allows you
|
194
|
+
# to create potentially expensive logging messages that are only
|
195
|
+
# called when the logger is configured to show them.
|
196
|
+
#
|
197
|
+
def debug message = nil, &block
|
198
|
+
if block_given?
|
199
|
+
add ::Logger::DEBUG, nil, message, &block
|
200
|
+
else
|
201
|
+
add ::Logger::DEBUG, message
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Log an `INFO` entry.
|
207
|
+
#
|
208
|
+
# @param [String, Hash] message The log entry payload, represented as
|
209
|
+
# either a string, a hash (JSON), or a hash (protocol buffer).
|
210
|
+
# @yield Evaluates to the message to log. This is not evaluated unless
|
211
|
+
# the logger's level is sufficient to log the message. This allows you
|
212
|
+
# to create potentially expensive logging messages that are only
|
213
|
+
# called when the logger is configured to show them.
|
214
|
+
#
|
215
|
+
def info message = nil, &block
|
216
|
+
if block_given?
|
217
|
+
add ::Logger::INFO, nil, message, &block
|
218
|
+
else
|
219
|
+
add ::Logger::INFO, message
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
##
|
224
|
+
# Log a `WARN` entry.
|
225
|
+
#
|
226
|
+
# @param [String, Hash] message The log entry payload, represented as
|
227
|
+
# either a string, a hash (JSON), or a hash (protocol buffer).
|
228
|
+
# @yield Evaluates to the message to log. This is not evaluated unless
|
229
|
+
# the logger's level is sufficient to log the message. This allows you
|
230
|
+
# to create potentially expensive logging messages that are only
|
231
|
+
# called when the logger is configured to show them.
|
232
|
+
#
|
233
|
+
def warn message = nil, &block
|
234
|
+
if block_given?
|
235
|
+
add ::Logger::WARN, nil, message, &block
|
236
|
+
else
|
237
|
+
add ::Logger::WARN, message
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
##
|
242
|
+
# Log an `ERROR` entry.
|
243
|
+
#
|
244
|
+
# @param [String, Hash] message The log entry payload, represented as
|
245
|
+
# either a string, a hash (JSON), or a hash (protocol buffer).
|
246
|
+
# @yield Evaluates to the message to log. This is not evaluated unless
|
247
|
+
# the logger's level is sufficient to log the message. This allows you
|
248
|
+
# to create potentially expensive logging messages that are only
|
249
|
+
# called when the logger is configured to show them.
|
250
|
+
#
|
251
|
+
def error message = nil, &block
|
252
|
+
if block_given?
|
253
|
+
add ::Logger::ERROR, nil, message, &block
|
254
|
+
else
|
255
|
+
add ::Logger::ERROR, message
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
##
|
260
|
+
# Log a `FATAL` entry.
|
261
|
+
#
|
262
|
+
# @param [String, Hash] message The log entry payload, represented as
|
263
|
+
# either a string, a hash (JSON), or a hash (protocol buffer).
|
264
|
+
# @yield Evaluates to the message to log. This is not evaluated unless
|
265
|
+
# the logger's level is sufficient to log the message. This allows you
|
266
|
+
# to create potentially expensive logging messages that are only
|
267
|
+
# called when the logger is configured to show them.
|
268
|
+
#
|
269
|
+
def fatal message = nil, &block
|
270
|
+
if block_given?
|
271
|
+
add ::Logger::FATAL, nil, message, &block
|
272
|
+
else
|
273
|
+
add ::Logger::FATAL, message
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
##
|
278
|
+
# Log an `UNKNOWN` entry. This will be printed no matter what the
|
279
|
+
# logger's current severity level is.
|
280
|
+
#
|
281
|
+
# @param [String, Hash] message The log entry payload, represented as
|
282
|
+
# either a string, a hash (JSON), or a hash (protocol buffer).
|
283
|
+
# @yield Evaluates to the message to log. This is not evaluated unless
|
284
|
+
# the logger's level is sufficient to log the message. This allows you
|
285
|
+
# to create potentially expensive logging messages that are only
|
286
|
+
# called when the logger is configured to show them.
|
287
|
+
#
|
288
|
+
def unknown message = nil, &block
|
289
|
+
if block_given?
|
290
|
+
add ::Logger::UNKNOWN, nil, message, &block
|
291
|
+
else
|
292
|
+
add ::Logger::UNKNOWN, message
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
##
|
297
|
+
# Log a message if the given severity is high enough. This is the
|
298
|
+
# generic logging method. Users will be more inclined to use {#debug},
|
299
|
+
# {#info}, {#warn}, {#error}, and {#fatal}.
|
300
|
+
#
|
301
|
+
# @param [Integer, String, Symbol] severity the integer code for or the
|
302
|
+
# name of the severity level
|
303
|
+
# @param [String, Hash] message The log entry payload, represented as
|
304
|
+
# either a string, a hash (JSON), or a hash (protocol buffer).
|
305
|
+
# @yield Evaluates to the message to log. This is not evaluated unless
|
306
|
+
# the logger's level is sufficient to log the message. This allows you
|
307
|
+
# to create potentially expensive logging messages that are only
|
308
|
+
# called when the logger is configured to show them.
|
309
|
+
#
|
310
|
+
def add severity, message = nil, progname = nil
|
311
|
+
return if @closed
|
312
|
+
|
313
|
+
severity = derive_severity(severity) || ::Logger::UNKNOWN
|
314
|
+
return true if severity < @level
|
315
|
+
|
316
|
+
if message.nil?
|
317
|
+
if block_given?
|
318
|
+
message = yield
|
319
|
+
else
|
320
|
+
message = progname
|
321
|
+
# progname = nil # TODO: Figure out what to do with the progname
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
write_entry severity, message unless @closed
|
326
|
+
true
|
327
|
+
end
|
328
|
+
alias log add
|
329
|
+
|
330
|
+
##
|
331
|
+
# Logs the given message at UNKNOWN severity.
|
332
|
+
#
|
333
|
+
# @param [String] msg The log entry payload as a string.
|
334
|
+
#
|
335
|
+
def << msg
|
336
|
+
unknown msg
|
337
|
+
self
|
338
|
+
end
|
339
|
+
|
340
|
+
##
|
341
|
+
# Returns `true` if the current severity level allows for sending
|
342
|
+
# `DEBUG` messages.
|
343
|
+
def debug?
|
344
|
+
@level <= ::Logger::DEBUG
|
345
|
+
end
|
346
|
+
|
347
|
+
##
|
348
|
+
# Returns `true` if the current severity level allows for sending `INFO`
|
349
|
+
# messages.
|
350
|
+
def info?
|
351
|
+
@level <= ::Logger::INFO
|
352
|
+
end
|
353
|
+
|
354
|
+
##
|
355
|
+
# Returns `true` if the current severity level allows for sending `WARN`
|
356
|
+
# messages.
|
357
|
+
def warn?
|
358
|
+
@level <= ::Logger::WARN
|
359
|
+
end
|
360
|
+
|
361
|
+
##
|
362
|
+
# Returns `true` if the current severity level allows for sending
|
363
|
+
# `ERROR` messages.
|
364
|
+
def error?
|
365
|
+
@level <= ::Logger::ERROR
|
366
|
+
end
|
367
|
+
|
368
|
+
##
|
369
|
+
# Returns `true` if the current severity level allows for sending
|
370
|
+
# `FATAL` messages.
|
371
|
+
def fatal?
|
372
|
+
@level <= ::Logger::FATAL
|
373
|
+
end
|
374
|
+
|
375
|
+
##
|
376
|
+
# Returns `true` if the current severity level allows for sending
|
377
|
+
# `UNKNOWN` messages.
|
378
|
+
def unknown?
|
379
|
+
@level <= ::Logger::UNKNOWN
|
380
|
+
end
|
381
|
+
|
382
|
+
##
|
383
|
+
# Sets the logging severity level.
|
384
|
+
#
|
385
|
+
# @param [Integer, String, Symbol] severity the integer code for or the
|
386
|
+
# name of the severity level
|
387
|
+
#
|
388
|
+
# @example
|
389
|
+
# require "google/cloud/logging"
|
390
|
+
#
|
391
|
+
# logging = Google::Cloud::Logging.new
|
392
|
+
#
|
393
|
+
# resource = logging.resource "gae_app",
|
394
|
+
# module_id: "1",
|
395
|
+
# version_id: "20150925t173233"
|
396
|
+
#
|
397
|
+
# logger = logging.logger "my_app_log", resource, env: :production
|
398
|
+
#
|
399
|
+
# logger.level = "INFO"
|
400
|
+
# logger.debug "Job started." # No log entry written
|
401
|
+
#
|
402
|
+
def level= severity
|
403
|
+
new_level = derive_severity severity
|
404
|
+
if new_level.nil?
|
405
|
+
raise ArgumentError, "invalid log level: #{severity}"
|
406
|
+
end
|
407
|
+
@level = new_level
|
408
|
+
end
|
409
|
+
alias sev_threshold= level=
|
410
|
+
alias local_level= level=
|
411
|
+
|
412
|
+
##
|
413
|
+
# Close the logging "device". This effectively disables logging from
|
414
|
+
# this logger; any further log messages will be silently ignored. The
|
415
|
+
# logger may be re-enabled by calling #reopen.
|
416
|
+
#
|
417
|
+
def close
|
418
|
+
@closed = true
|
419
|
+
self
|
420
|
+
end
|
421
|
+
|
422
|
+
##
|
423
|
+
# Re-enable logging if the logger has been closed.
|
424
|
+
#
|
425
|
+
# Note that this method accepts a "logdev" argument for compatibility
|
426
|
+
# with the standard Ruby Logger class; however, this argument is
|
427
|
+
# ignored because this logger does not use a log device.
|
428
|
+
#
|
429
|
+
def reopen _logdev = nil
|
430
|
+
@closed = false
|
431
|
+
self
|
432
|
+
end
|
433
|
+
|
434
|
+
##
|
435
|
+
# Track a given trace_id by associating it with the current
|
436
|
+
# Thread
|
437
|
+
#
|
438
|
+
# @deprecated Use add_request_info
|
439
|
+
#
|
440
|
+
def add_trace_id trace_id
|
441
|
+
add_request_info trace_id: trace_id
|
442
|
+
end
|
443
|
+
|
444
|
+
##
|
445
|
+
# Associate request data with the current Thread. You may provide
|
446
|
+
# either the individual pieces of data (trace ID, log name) or a
|
447
|
+
# populated RequestInfo object.
|
448
|
+
#
|
449
|
+
# @param [RequestInfo] info Info about the current request. Optional.
|
450
|
+
# If not present, a new RequestInfo is created using the remaining
|
451
|
+
# parameters.
|
452
|
+
# @param [String, nil] trace_id The trace ID, or `nil` if no trace ID
|
453
|
+
# should be logged.
|
454
|
+
# @param [String, nil] log_name The log name to use, or nil to use
|
455
|
+
# this logger's default.
|
456
|
+
# @param [Hash, nil] env The request's Rack environment or `nil` if not
|
457
|
+
# available.
|
458
|
+
#
|
459
|
+
def add_request_info info: nil, env: nil, trace_id: nil, log_name: nil,
|
460
|
+
trace_sampled: nil
|
461
|
+
info ||= RequestInfo.new trace_id, log_name, env, trace_sampled
|
462
|
+
|
463
|
+
@request_info_var.value = info
|
464
|
+
|
465
|
+
info
|
466
|
+
end
|
467
|
+
|
468
|
+
##
|
469
|
+
# Get the request data for the current Thread
|
470
|
+
#
|
471
|
+
# @return [RequestInfo, nil] The request data for the current thread,
|
472
|
+
# or `nil` if there is no data set.
|
473
|
+
#
|
474
|
+
def request_info
|
475
|
+
@request_info_var.value
|
476
|
+
end
|
477
|
+
|
478
|
+
##
|
479
|
+
# Untrack the RequestInfo that's associated with current Thread
|
480
|
+
#
|
481
|
+
# @return [RequestInfo] The info that's being deleted
|
482
|
+
#
|
483
|
+
def delete_request_info
|
484
|
+
@request_info_var.value = nil
|
485
|
+
end
|
486
|
+
|
487
|
+
##
|
488
|
+
# @deprecated Use delete_request_info
|
489
|
+
alias delete_trace_id delete_request_info
|
490
|
+
|
491
|
+
##
|
492
|
+
# No-op method. Created to match the spec of ActiveSupport::Logger#flush
|
493
|
+
# method when used in Rails application.
|
494
|
+
def flush
|
495
|
+
self
|
496
|
+
end
|
497
|
+
|
498
|
+
##
|
499
|
+
# Filter out low severity messages within block.
|
500
|
+
#
|
501
|
+
# @param [Integer] temp_level Severity threshold to filter within the
|
502
|
+
# block. Messages with lower severity will be blocked. Default
|
503
|
+
# ::Logger::ERROR
|
504
|
+
#
|
505
|
+
# @example
|
506
|
+
# require "google/cloud/logging"
|
507
|
+
#
|
508
|
+
# logging = Google::Cloud::Logging.new
|
509
|
+
#
|
510
|
+
# resource = logging.resource "gae_app",
|
511
|
+
# module_id: "1",
|
512
|
+
# version_id: "20150925t173233"
|
513
|
+
#
|
514
|
+
# logger = logging.logger "my_app_log", resource, env: :production
|
515
|
+
#
|
516
|
+
# logger.silence do
|
517
|
+
# logger.info "Info message" # No log entry written
|
518
|
+
# logger.error "Error message" # Log entry written
|
519
|
+
# end
|
520
|
+
def silence temp_level = ::Logger::ERROR
|
521
|
+
if silencer
|
522
|
+
begin
|
523
|
+
old_level = level
|
524
|
+
self.level = temp_level
|
525
|
+
|
526
|
+
yield self
|
527
|
+
ensure
|
528
|
+
self.level = old_level
|
529
|
+
end
|
530
|
+
else
|
531
|
+
yield self
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
protected
|
536
|
+
|
537
|
+
##
|
538
|
+
# @private Write a log entry to the Stackdriver Logging service.
|
539
|
+
def write_entry severity, message
|
540
|
+
entry = Entry.new.tap do |e|
|
541
|
+
e.timestamp = Time.now
|
542
|
+
e.severity = gcloud_severity severity
|
543
|
+
e.payload = message
|
544
|
+
end
|
545
|
+
|
546
|
+
actual_log_name = log_name
|
547
|
+
info = request_info
|
548
|
+
if info
|
549
|
+
actual_log_name = info.log_name || actual_log_name
|
550
|
+
unless info.trace_id.nil? || @project.nil?
|
551
|
+
entry.trace = "projects/#{@project}/traces/#{info.trace_id}"
|
552
|
+
end
|
553
|
+
entry.trace_sampled = info.trace_sampled if entry.trace_sampled.nil?
|
554
|
+
end
|
555
|
+
|
556
|
+
writer.write_entries entry, log_name: actual_log_name,
|
557
|
+
resource: resource,
|
558
|
+
labels: entry_labels(info)
|
559
|
+
end
|
560
|
+
|
561
|
+
##
|
562
|
+
# @private generate the labels hash for a log entry.
|
563
|
+
def entry_labels info
|
564
|
+
merged_labels = {}
|
565
|
+
|
566
|
+
if info && !info.trace_id.nil?
|
567
|
+
merged_labels["traceId"] = info.trace_id
|
568
|
+
if Google::Cloud.env.app_engine?
|
569
|
+
merged_labels["appengine.googleapis.com/trace_id"] = info.trace_id
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
request_env = info && info.env || {}
|
574
|
+
|
575
|
+
compute_labels(request_env).merge merged_labels
|
576
|
+
end
|
577
|
+
|
578
|
+
##
|
579
|
+
# @private Get the logger level number from severity value object.
|
580
|
+
def derive_severity severity
|
581
|
+
return severity if severity.is_a? Integer
|
582
|
+
|
583
|
+
downcase_severity = severity.to_s.downcase
|
584
|
+
case downcase_severity
|
585
|
+
when "debug".freeze then ::Logger::DEBUG
|
586
|
+
when "info".freeze then ::Logger::INFO
|
587
|
+
when "warn".freeze then ::Logger::WARN
|
588
|
+
when "error".freeze then ::Logger::ERROR
|
589
|
+
when "fatal".freeze then ::Logger::FATAL
|
590
|
+
when "unknown".freeze then ::Logger::UNKNOWN
|
591
|
+
end
|
592
|
+
end
|
593
|
+
|
594
|
+
##
|
595
|
+
# @private Get Google Cloud deverity from logger level number.
|
596
|
+
def gcloud_severity severity_int
|
597
|
+
%i[DEBUG INFO WARNING ERROR CRITICAL DEFAULT][severity_int]
|
598
|
+
rescue StandardError
|
599
|
+
:DEFAULT
|
600
|
+
end
|
601
|
+
|
602
|
+
##
|
603
|
+
# @private Get current thread id
|
604
|
+
def current_thread_id
|
605
|
+
Thread.current.object_id
|
606
|
+
end
|
607
|
+
|
608
|
+
private
|
609
|
+
|
610
|
+
##
|
611
|
+
# @private Compute values for labels
|
612
|
+
def compute_labels request_env
|
613
|
+
Hash[
|
614
|
+
labels.map do |k, value_or_proc|
|
615
|
+
[k, compute_label_value(request_env, value_or_proc)]
|
616
|
+
end
|
617
|
+
]
|
618
|
+
end
|
619
|
+
|
620
|
+
##
|
621
|
+
# @private Compute individual label value.
|
622
|
+
# Value can be a Proc (function of the request env) or a static value.
|
623
|
+
def compute_label_value request_env, value_or_proc
|
624
|
+
if value_or_proc.respond_to? :call
|
625
|
+
value_or_proc.call request_env
|
626
|
+
else
|
627
|
+
value_or_proc
|
628
|
+
end
|
629
|
+
end
|
630
|
+
end
|
631
|
+
end
|
632
|
+
end
|
633
|
+
end
|