google-cloud-logging 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +18 -0
  3. data/AUTHENTICATION.md +178 -0
  4. data/CHANGELOG.md +407 -0
  5. data/CODE_OF_CONDUCT.md +40 -0
  6. data/CONTRIBUTING.md +188 -0
  7. data/INSTRUMENTATION.md +71 -0
  8. data/LICENSE +201 -0
  9. data/LOGGING.md +32 -0
  10. data/OVERVIEW.md +321 -0
  11. data/TROUBLESHOOTING.md +31 -0
  12. data/lib/google-cloud-logging.rb +161 -0
  13. data/lib/google/cloud/logging.rb +188 -0
  14. data/lib/google/cloud/logging/async_writer.rb +513 -0
  15. data/lib/google/cloud/logging/convert.rb +70 -0
  16. data/lib/google/cloud/logging/credentials.rb +44 -0
  17. data/lib/google/cloud/logging/entry.rb +528 -0
  18. data/lib/google/cloud/logging/entry/http_request.rb +167 -0
  19. data/lib/google/cloud/logging/entry/list.rb +178 -0
  20. data/lib/google/cloud/logging/entry/operation.rb +91 -0
  21. data/lib/google/cloud/logging/entry/source_location.rb +85 -0
  22. data/lib/google/cloud/logging/errors.rb +101 -0
  23. data/lib/google/cloud/logging/log/list.rb +156 -0
  24. data/lib/google/cloud/logging/logger.rb +633 -0
  25. data/lib/google/cloud/logging/metric.rb +168 -0
  26. data/lib/google/cloud/logging/metric/list.rb +170 -0
  27. data/lib/google/cloud/logging/middleware.rb +307 -0
  28. data/lib/google/cloud/logging/project.rb +838 -0
  29. data/lib/google/cloud/logging/rails.rb +232 -0
  30. data/lib/google/cloud/logging/resource.rb +85 -0
  31. data/lib/google/cloud/logging/resource_descriptor.rb +137 -0
  32. data/lib/google/cloud/logging/resource_descriptor/list.rb +175 -0
  33. data/lib/google/cloud/logging/service.rb +239 -0
  34. data/lib/google/cloud/logging/sink.rb +315 -0
  35. data/lib/google/cloud/logging/sink/list.rb +168 -0
  36. data/lib/google/cloud/logging/version.rb +22 -0
  37. metadata +304 -0
@@ -0,0 +1,32 @@
1
+ # Enabling gRPC Logging
2
+
3
+ To enable logging for this library, set the logger for the underlying
4
+ [gRPC](https://github.com/grpc/grpc/tree/master/src/ruby) library. The logger
5
+ that you set may be a Ruby stdlib
6
+ [`Logger`](https://ruby-doc.org/stdlib-2.5.0/libdoc/logger/rdoc/Logger.html) as
7
+ shown below, or a
8
+ [`Google::Cloud::Logging::Logger`](https://googleapis.dev/ruby/google-cloud-logging/latest)
9
+ that will write logs to [Stackdriver
10
+ Logging](https://cloud.google.com/logging/). See
11
+ [grpc/logconfig.rb](https://github.com/grpc/grpc/blob/master/src/ruby/lib/grpc/logconfig.rb)
12
+ and the gRPC
13
+ [spec_helper.rb](https://github.com/grpc/grpc/blob/master/src/ruby/spec/spec_helper.rb)
14
+ for additional information.
15
+
16
+ Configuring a Ruby stdlib logger:
17
+
18
+ ```ruby
19
+ require "logger"
20
+
21
+ module MyLogger
22
+ LOGGER = Logger.new $stderr, level: Logger::WARN
23
+ def logger
24
+ LOGGER
25
+ end
26
+ end
27
+
28
+ # Define a gRPC module-level logger method before grpc/logconfig.rb loads.
29
+ module GRPC
30
+ extend MyLogger
31
+ end
32
+ ```
@@ -0,0 +1,321 @@
1
+ # Stackdriver Logging
2
+
3
+ The Stackdriver Logging service collects and stores logs from applications and
4
+ services on the Google Cloud Platform, giving you fine-grained, programmatic
5
+ control over your projects' logs. You can use the Stackdriver Logging API to:
6
+
7
+ * [Read and filter log entries](#listing-log-entries)
8
+ * [Export your log entries](#exporting-log-entries) to Cloud Storage,
9
+ BigQuery, or Cloud Pub/Sub
10
+ * [Create logs-based metrics](#creating-logs-based-metrics) for use in
11
+ Cloud Monitoring
12
+ * [Write log entries](#writing-log-entries)
13
+
14
+ For general information about Stackdriver Logging, read [Stackdriver Logging
15
+ Documentation](https://cloud.google.com/logging/docs/).
16
+
17
+ The goal of google-cloud is to provide an API that is comfortable to Rubyists.
18
+ Your authentication credentials are detected automatically in Google Cloud
19
+ Platform (GCP), including Google Compute Engine (GCE), Google Kubernetes Engine
20
+ (GKE), Google App Engine (GAE), Google Cloud Functions (GCF) and Cloud Run. In
21
+ other environments you can configure authentication easily, either directly in
22
+ your code or via environment variables. Read more about the options for
23
+ connecting in the {file:AUTHENTICATION.md Authentication Guide}.
24
+
25
+ ## Listing log entries
26
+
27
+ Stackdriver Logging gathers log entries from many services, including Google App
28
+ Engine and Google Compute Engine. (See the [List of Log
29
+ Types](https://cloud.google.com/logging/docs/view/logs_index).) In addition, you
30
+ can write your own log entries to the service.
31
+
32
+ {Google::Cloud::Logging::Project#entries Project#entries} returns the
33
+ {Google::Cloud::Logging::Entry Entry} records belonging to your project:
34
+
35
+ ```ruby
36
+ require "google/cloud/logging"
37
+
38
+ logging = Google::Cloud::Logging.new
39
+ entries = logging.entries
40
+ entries.each do |e|
41
+ puts "[#{e.timestamp}] #{e.log_name} #{e.payload.inspect}"
42
+ end
43
+ ```
44
+
45
+ You can narrow the results to a single log using an [advanced logs
46
+ filter](https://cloud.google.com/logging/docs/view/advanced_filters). A log is a
47
+ named collection of entries. Logs can be produced by Google Cloud Platform
48
+ services, by third-party services, or by your applications. For example, the log
49
+ `compute.googleapis.com/activity_log` is produced by Google Compute Engine. Logs
50
+ are simply referenced by name in google-cloud. There is no `Log` type in
51
+ google-cloud or `Log` resource in the Stackdriver Logging API.
52
+
53
+ ```ruby
54
+ require "google/cloud/logging"
55
+
56
+ logging = Google::Cloud::Logging.new
57
+ entries = logging.entries filter: "logName:syslog"
58
+ entries.each do |e|
59
+ puts "[#{e.timestamp}] #{e.payload.inspect}"
60
+ end
61
+ ```
62
+
63
+ You can also order the log entries by `timestamp`.
64
+
65
+ ```ruby
66
+ require "google/cloud/logging"
67
+
68
+ logging = Google::Cloud::Logging.new
69
+ entries = logging.entries order: "timestamp desc"
70
+ entries.each do |e|
71
+ puts "[#{e.timestamp}] #{e.log_name}"
72
+ end
73
+ ```
74
+
75
+ ## Exporting log entries
76
+
77
+ Stackdriver Logging lets you export log entries to destinations including Google
78
+ Cloud Storage buckets (for long term log storage), Google BigQuery datasets (for
79
+ log analysis), and Google Pub/Sub (for streaming to other applications).
80
+
81
+ ### Creating sinks
82
+
83
+ A {Google::Cloud::Logging::Sink Sink} is an object that lets you to specify a
84
+ set of log entries to export.
85
+
86
+ In addition to the name of the sink and the export destination,
87
+ {Google::Cloud::Logging::Project#create_sink Project#create_sink} accepts an
88
+ [advanced logs
89
+ filter](https://cloud.google.com/logging/docs/view/advanced_filters) to narrow
90
+ the collection.
91
+
92
+ Before creating the sink, ensure that you have granted `cloud-logs@google.com`
93
+ permission to write logs to the destination. See [Exporting Logs
94
+ (V2)](https://cloud.google.com/logging/docs/export/configure_export_v2).
95
+
96
+ ```ruby
97
+ require "google/cloud/storage"
98
+ require "google/cloud/logging"
99
+
100
+ storage = Google::Cloud::Storage.new
101
+
102
+ bucket = storage.create_bucket "my-logs-bucket"
103
+
104
+ # Grant owner permission to Stackdriver Logging service
105
+ email = "cloud-logs@google.com"
106
+ bucket.acl.add_owner "group-#{email}"
107
+
108
+ logging = Google::Cloud::Logging.new
109
+
110
+ sink = logging.create_sink "my-sink",
111
+ "storage.googleapis.com/#{bucket.id}"
112
+ ```
113
+
114
+ When you create a sink, only new log entries are exported. Stackdriver Logging
115
+ does not send previously-ingested log entries to the sink's destination.
116
+
117
+ ### Listing sinks
118
+
119
+ You can also list the sinks belonging to your project with
120
+ {Google::Cloud::Logging::Project#sinks Project#sinks}.
121
+
122
+ ```ruby
123
+ require "google/cloud/logging"
124
+
125
+ logging = Google::Cloud::Logging.new
126
+ sinks = logging.sinks
127
+ sinks.each do |s|
128
+ puts "#{s.name}: #{s.filter} -> #{s.destination}"
129
+ end
130
+ ```
131
+
132
+ ## Creating logs-based metrics
133
+
134
+ You can use log entries in your project as the basis for [Google Cloud
135
+ Monitoring](https://cloud.google.com/monitoring/docs) metrics. These metrics can
136
+ then be used to produce Cloud Monitoring reports and alerts.
137
+
138
+ ### Creating metrics
139
+
140
+ A metric is a measured value that can be used to assess a system. Use
141
+ {Google::Cloud::Logging::Project#create_metric Project#create_metric} to
142
+ configure a {Google::Cloud::Logging::Metric Metric} based on a collection of
143
+ log entries matching an [advanced logs
144
+ filter](https://cloud.google.com/logging/docs/view/advanced_filters).
145
+
146
+ ```ruby
147
+ require "google/cloud/logging"
148
+
149
+ logging = Google::Cloud::Logging.new
150
+ metric = logging.create_metric "errors", "severity>=ERROR"
151
+ ```
152
+
153
+ ### Listing metrics
154
+
155
+ You can also list the metrics belonging to your project with
156
+ {Google::Cloud::Logging::Project#metrics Project#metrics}.
157
+
158
+ ```ruby
159
+ require "google/cloud/logging"
160
+
161
+ logging = Google::Cloud::Logging.new
162
+ metrics = logging.metrics
163
+ metrics.each do |m|
164
+ puts "#{m.name}: #{m.filter}"
165
+ end
166
+ ```
167
+
168
+ ## Writing log entries
169
+
170
+ An {Google::Cloud::Logging::Entry} is composed of metadata and a payload. The
171
+ payload is traditionally a message string, but in Stackdriver Logging it can
172
+ also be a JSON or protocol buffer object. A single log can have entries with
173
+ different payload types. In addition to the payload, your argument(s) to
174
+ {Google::Cloud::Logging::Project#write_entries Project#write_entries} must also
175
+ contain a log name and a resource.
176
+
177
+ ```ruby
178
+ require "google/cloud/logging"
179
+
180
+ logging = Google::Cloud::Logging.new
181
+
182
+ entry = logging.entry
183
+ entry.payload = "Job started."
184
+ entry.log_name = "my_app_log"
185
+ entry.resource.type = "gae_app"
186
+ entry.resource.labels[:module_id] = "1"
187
+ entry.resource.labels[:version_id] = "20150925t173233"
188
+
189
+ logging.write_entries entry
190
+ ```
191
+
192
+ To write a JSON payload to the log, simply pass a hash argument:
193
+
194
+ ```ruby
195
+ require "google/cloud/logging"
196
+
197
+ logging = Google::Cloud::Logging.new
198
+
199
+ entry = logging.entry
200
+ entry.payload = { "stats" => { "a" => 8, "b" => 12.5} }
201
+ entry.log_name = "my_app_log"
202
+ entry.resource.type = "gae_app"
203
+ entry.resource.labels[:module_id] = "1"
204
+ entry.resource.labels[:version_id] = "20150925t173233"
205
+
206
+ logging.write_entries entry
207
+ ```
208
+
209
+ If you write a collection of log entries, you can provide the log name,
210
+ resource, and/or labels hash to be used for all of the entries, and omit these
211
+ values from the individual entries.
212
+
213
+ ```ruby
214
+ require "google/cloud/logging"
215
+
216
+ logging = Google::Cloud::Logging.new
217
+
218
+ entry1 = logging.entry
219
+ entry1.payload = "Job started."
220
+ entry2 = logging.entry
221
+ entry2.payload = "Job completed."
222
+ labels = { job_size: "large", job_code: "red" }
223
+
224
+ resource = logging.resource "gae_app",
225
+ "module_id" => "1",
226
+ "version_id" => "20150925t173233"
227
+
228
+ logging.write_entries [entry1, entry2],
229
+ log_name: "my_app_log",
230
+ resource: resource,
231
+ labels: labels
232
+ ```
233
+
234
+ Normally, writing log entries is done synchronously; the call to
235
+ {Google::Cloud::Logging::Project#write_entries Project#write_entries} will block
236
+ until it has either completed transmitting the data or encountered an error. To
237
+ "fire and forget" without blocking, use {Google::Cloud::Logging::AsyncWriter
238
+ AsyncWriter}; it spins up a background thread that writes log entries in
239
+ batches. Calls to {Google::Cloud::Logging::AsyncWriter#write_entries
240
+ AsyncWriter#write_entries} simply add entries to its work queue and return
241
+ immediately.
242
+
243
+ ```ruby
244
+ require "google/cloud/logging"
245
+
246
+ logging = Google::Cloud::Logging.new
247
+ async = logging.async_writer
248
+
249
+ entry1 = logging.entry
250
+ entry1.payload = "Job started."
251
+ entry2 = logging.entry
252
+ entry2.payload = "Job completed."
253
+ labels = { job_size: "large", job_code: "red" }
254
+
255
+ resource = logging.resource "gae_app",
256
+ "module_id" => "1",
257
+ "version_id" => "20150925t173233"
258
+
259
+ async.write_entries [entry1, entry2],
260
+ log_name: "my_app_log",
261
+ resource: resource,
262
+ labels: labels,
263
+ partial_success: true
264
+ ```
265
+
266
+ ### Creating a Ruby Logger implementation
267
+
268
+ If your environment requires a logger instance that is API-compatible with
269
+ Ruby's standard library [Logger](http://ruby-doc.org/stdlib/libdoc/logger/rdoc),
270
+ you can use {Google::Cloud::Logging::Project#logger Project#logger} to create
271
+ one.
272
+
273
+ ```ruby
274
+ require "google/cloud/logging"
275
+
276
+ logging = Google::Cloud::Logging.new
277
+
278
+ resource = logging.resource "gae_app",
279
+ module_id: "1",
280
+ version_id: "20150925t173233"
281
+
282
+ logger = logging.logger "my_app_log", resource, env: :production
283
+ logger.info "Job started."
284
+ ```
285
+
286
+ By default, the logger instance writes log entries asynchronously in a
287
+ background thread using an {Google::Cloud::Logging::AsyncWriter AsyncWriter}. If
288
+ you want to customize or disable asynchronous writing, you may call the Logger
289
+ constructor directly.
290
+
291
+ ```ruby
292
+ require "google/cloud/logging"
293
+
294
+ logging = Google::Cloud::Logging.new
295
+
296
+ resource = logging.resource "gae_app",
297
+ module_id: "1",
298
+ version_id: "20150925t173233"
299
+
300
+ logger = Google::Cloud::Logging::Logger.new logging,
301
+ "my_app_log",
302
+ resource,
303
+ {env: :production}
304
+ logger.info "Log entry written synchronously."
305
+ ```
306
+
307
+ ## Configuring timeout
308
+
309
+ You can configure the request `timeout` value in seconds.
310
+
311
+ ```ruby
312
+ require "google/cloud/logging"
313
+
314
+ logging = Google::Cloud::Logging.new timeout: 120
315
+ ```
316
+
317
+ ## Additional information
318
+
319
+ Stackdriver Logging can be configured to be used in Rack applications or to use
320
+ gRPC's logging. To learn more, see the {file:INSTRUMENTATION.md Instrumentation
321
+ Guide} and {file:LOGGING.md Logging guide}.
@@ -0,0 +1,31 @@
1
+ # Troubleshooting
2
+
3
+ ## Where can I get more help?
4
+
5
+ ### Ask the Community
6
+
7
+ If you have a question about how to use a Google Cloud client library in your
8
+ project or are stuck in the Developer's console and don't know where to turn,
9
+ it's possible your questions have already been addressed by the community.
10
+
11
+ First, check out the appropriate tags on StackOverflow:
12
+ - [`google-cloud-platform+ruby+logging`][so-ruby]
13
+
14
+ Next, try searching through the issues on GitHub:
15
+
16
+ - [`api:logging` issues][gh-search-ruby]
17
+
18
+ Still nothing?
19
+
20
+ ### Ask the Developers
21
+
22
+ If you're experiencing a bug with the code, or have an idea for how it can be
23
+ improved, *please* create a new issue on GitHub so we can talk about it.
24
+
25
+ - [New issue][gh-ruby]
26
+
27
+ [so-ruby]: http://stackoverflow.com/questions/tagged/google-cloud-platform+ruby+logging
28
+
29
+ [gh-search-ruby]: https://github.com/googleapis/google-cloud-ruby/issues?q=label%3A%22api%3A+logging%22
30
+
31
+ [gh-ruby]: https://github.com/googleapis/google-cloud-ruby/issues/new
@@ -0,0 +1,161 @@
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
+ ##
17
+ # This file is here to be autorequired by bundler, so that the
18
+ # Google::Cloud.logging and Google::Cloud#logging methods can be available, but
19
+ # the library and all dependencies won't be loaded until required and used.
20
+
21
+
22
+ gem "google-cloud-core"
23
+ require "google/cloud" unless defined? Google::Cloud.new
24
+ require "google/cloud/config"
25
+ require "googleauth"
26
+
27
+ module Google
28
+ module Cloud
29
+ ##
30
+ # Creates a new object for connecting to the Stackdriver Logging service.
31
+ # Each call creates a new connection.
32
+ #
33
+ # For more information on connecting to Google Cloud see the
34
+ # {file:AUTHENTICATION.md Authentication Guide}.
35
+ #
36
+ # @param [String, Array<String>] scope The OAuth 2.0 scopes controlling the
37
+ # set of resources and operations that the connection can access. See
38
+ # [Using OAuth 2.0 to Access Google
39
+ # APIs](https://developers.google.com/identity/protocols/OAuth2).
40
+ #
41
+ # The default scope is:
42
+ #
43
+ # * `https://www.googleapis.com/auth/logging.admin`
44
+ #
45
+ # @param [Integer] timeout Default timeout to use in requests. Optional.
46
+ #
47
+ # @return [Google::Cloud::Logging::Project]
48
+ #
49
+ # @example
50
+ # require "google/cloud"
51
+ #
52
+ # gcloud = Google::Cloud.new
53
+ # logging = gcloud.logging
54
+ #
55
+ # entries = logging.entries
56
+ # entries.each do |e|
57
+ # puts "[#{e.timestamp}] #{e.log_name} #{e.payload.inspect}"
58
+ # end
59
+ #
60
+ # @example The default scope can be overridden with the `scope` option:
61
+ # require "google/cloud"
62
+ #
63
+ # gcloud = Google::Cloud.new
64
+ # platform_scope = "https://www.googleapis.com/auth/cloud-platform"
65
+ # logging = gcloud.logging scope: platform_scope
66
+ #
67
+ def logging scope: nil, timeout: nil
68
+ timeout ||= @timeout
69
+ Google::Cloud.logging @project, @keyfile, scope: scope,
70
+ timeout: timeout
71
+ end
72
+
73
+ ##
74
+ # Creates a new object for connecting to the Stackdriver Logging service.
75
+ # Each call creates a new connection.
76
+ #
77
+ # For more information on connecting to Google Cloud see the
78
+ # {file:AUTHENTICATION.md Authentication Guide}.
79
+ #
80
+ # @param [String] project_id Project identifier for the Stackdriver Logging
81
+ # service you are connecting to. If not present, the default project for
82
+ # the credentials is used.
83
+ # @param [String, Hash, Google::Auth::Credentials] credentials The path to
84
+ # the keyfile as a String, the contents of the keyfile as a Hash, or a
85
+ # Google::Auth::Credentials object. (See {Logging::Credentials})
86
+ # @param [String, Array<String>] scope The OAuth 2.0 scopes controlling the
87
+ # set of resources and operations that the connection can access. See
88
+ # [Using OAuth 2.0 to Access Google
89
+ # APIs](https://developers.google.com/identity/protocols/OAuth2).
90
+ #
91
+ # The default scope is:
92
+ #
93
+ # * `https://www.googleapis.com/auth/logging.admin`
94
+ #
95
+ # @param [Integer] timeout Default timeout to use in requests. Optional.
96
+ #
97
+ # @return [Google::Cloud::Logging::Project]
98
+ #
99
+ # @example
100
+ # require "google/cloud"
101
+ #
102
+ # logging = Google::Cloud.logging
103
+ #
104
+ # entries = logging.entries
105
+ # entries.each do |e|
106
+ # puts "[#{e.timestamp}] #{e.log_name} #{e.payload.inspect}"
107
+ # end
108
+ #
109
+ def self.logging project_id = nil, credentials = nil, scope: nil, timeout: nil
110
+ require "google/cloud/logging"
111
+ Google::Cloud::Logging.new project_id: project_id,
112
+ credentials: credentials,
113
+ scope: scope, timeout: timeout
114
+ end
115
+ end
116
+ end
117
+
118
+ # Add logging to top-level configuration
119
+ Google::Cloud.configure do |config|
120
+ unless config.field? :use_logging
121
+ config.add_field! :use_logging, nil, enum: [true, false]
122
+ end
123
+ end
124
+
125
+ # Set the default logging configuration
126
+ Google::Cloud.configure.add_config! :logging do |config|
127
+ default_project = Google::Cloud::Config.deferred do
128
+ ENV["LOGGING_PROJECT"]
129
+ end
130
+ default_creds = Google::Cloud::Config.deferred do
131
+ Google::Cloud::Config.credentials_from_env \
132
+ "LOGGING_CREDENTIALS", "LOGGING_CREDENTIALS_JSON",
133
+ "LOGGING_KEYFILE", "LOGGING_KEYFILE_JSON"
134
+ end
135
+ default_scopes = [
136
+ "https://www.googleapis.com/auth/cloud-platform",
137
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
138
+ "https://www.googleapis.com/auth/logging.admin",
139
+ "https://www.googleapis.com/auth/logging.read",
140
+ "https://www.googleapis.com/auth/logging.write"
141
+ ]
142
+
143
+ config.add_field! :project_id, default_project, match: String, allow_nil: true
144
+ config.add_alias! :project, :project_id
145
+ config.add_field! :credentials, default_creds,
146
+ match: [String, Hash, Google::Auth::Credentials],
147
+ allow_nil: true
148
+ config.add_alias! :keyfile, :credentials
149
+ config.add_field! :scope, default_scopes, match: [String, Array]
150
+ config.add_field! :timeout, nil, match: Integer
151
+ config.add_field! :endpoint, "logging.googleapis.com", match: String
152
+ config.add_field! :log_name, nil, match: String
153
+ config.add_field! :log_name_map, nil, match: Hash
154
+ config.add_field! :labels, nil, match: Hash
155
+ config.add_config! :monitored_resource do |mrconfig|
156
+ mrconfig.add_field! :type, nil, match: String
157
+ mrconfig.add_field! :labels, nil, match: Hash
158
+ end
159
+ config.add_field! :set_default_logger_on_rails_init, nil, enum: [true, false]
160
+ config.add_field! :on_error, nil, match: Proc
161
+ end