rack-action_logger 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c8e8c03cf1b03abb219ce366f186470e1463b076
4
- data.tar.gz: 66ebdaa2cf3853bc60ae5ffcadb06716b38d9558
3
+ metadata.gz: 56b290ce696ada82b2b73deb7d7ddc038de28bbb
4
+ data.tar.gz: 403d7663fb1cc6bb013ac4de372886cb54366b2d
5
5
  SHA512:
6
- metadata.gz: 73a13a6749b1e4da13e799edad40fdda78b61c8b97a172bb806de803a3128667ae9dd5558b1f77046168988505f51feb9759fde290443a4f7c3a72e06ee339a2
7
- data.tar.gz: 84437cfd8af9b5882c525532eb0d94436521b2b99e9dc8fe04e25967794701c94a7fceef1375f8b9c8a0f995c1f2060e145afe534c296b0c0a040ce3bd1d7cb4
6
+ metadata.gz: 10da516b0a30cf0eae2953751c2333e45d2045343b1064fc5df8770241ba9e8f1560466d508bd0795b3da71ad9bf08e9f30f15270eb7ab5e155759cca8c0974e
7
+ data.tar.gz: 6170bfd88ac5231556cee46ad168ada907ad0bad14fe3d574c851e0bf755ba2682375d6c99068f796ecf6b83e6fee779981cdd05caf12e9ec4ea78afcf8f94df
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-action_logger (0.1.1)
4
+ rack-action_logger (0.1.2)
5
5
  activesupport
6
6
  fluent-logger (~> 0.5)
7
+ woothee (~> 1.4)
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
@@ -20,6 +21,9 @@ GEM
20
21
  i18n (0.7.0)
21
22
  minitest (5.9.1)
22
23
  msgpack (1.0.2)
24
+ rack (2.0.1)
25
+ rack-test (0.6.3)
26
+ rack (>= 1.0)
23
27
  rake (10.5.0)
24
28
  rspec (3.5.0)
25
29
  rspec-core (~> 3.5.0)
@@ -37,6 +41,7 @@ GEM
37
41
  thread_safe (0.3.5)
38
42
  tzinfo (1.2.2)
39
43
  thread_safe (~> 0.1)
44
+ woothee (1.5.0)
40
45
 
41
46
  PLATFORMS
42
47
  ruby
@@ -44,6 +49,7 @@ PLATFORMS
44
49
  DEPENDENCIES
45
50
  bundler (~> 1.13)
46
51
  rack-action_logger!
52
+ rack-test (~> 0.6.3)
47
53
  rake (~> 10.0)
48
54
  rspec (~> 3.0)
49
55
 
data/README.md CHANGED
@@ -12,7 +12,60 @@ It is intended to collect user request log, action log and any other custome log
12
12
 
13
13
  ## Sample Logs
14
14
 
15
- ![sample logs](docs/sample_log.png)
15
+ ### Request log
16
+
17
+ ```json
18
+ {
19
+ "message": {
20
+ "path": "/",
21
+ "method": "GET",
22
+ "params": {
23
+ "password": "[FILTERED]"
24
+ },
25
+ "request_headers": {
26
+ "HTTP_VERSION": "HTTP/1.1",
27
+ "HTTP_HOST": "localhost:3000",
28
+ "HTTP_CONNECTION": "keep-alive",
29
+ "HTTP_UPGRADE_INSECURE_REQUESTS": "1",
30
+ "HTTP_USER_AGENT": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
31
+ "HTTP_ACCEPT": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
32
+ "HTTP_ACCEPT_ENCODING": "gzip, deflate, sdch, br",
33
+ "HTTP_ACCEPT_LANGUAGE": "ja,en-US;q=0.8,en;q=0.6",
34
+ "HTTP_COOKIE": "xxx"
35
+ },
36
+ "status_code": 200,
37
+ "remote_ip": "127.0.0.1",
38
+ "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
39
+ "device": "pc",
40
+ "os": "Mac OSX",
41
+ "browser": "Chrome",
42
+ "browser_version": "54.0.2840.98",
43
+ "request_id": "150a6ac9-0fd9-4a23-a313-d18da1e35911",
44
+ "response_headers": {
45
+ "X-Frame-Options": "SAMEORIGIN",
46
+ "X-XSS-Protection": "1; mode=block",
47
+ "X-Content-Type-Options": "nosniff",
48
+ "Content-Type": "text/html; charset=utf-8"
49
+ },
50
+ "response_json_body": {
51
+ },
52
+ "tag": "action.rack",
53
+ "user_id": 123
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### Append log
59
+
60
+ ```json
61
+ {
62
+ "message": {
63
+ "request_id": "150a6ac9-0fd9-4a23-a313-d18da1e35911",
64
+ "value": "with_tag",
65
+ "tag": "action.activities"
66
+ }
67
+ }
68
+ ```
16
69
 
17
70
  Under example folder, there are sample Rails applications to see how these sample logs are created.
18
71
 
@@ -54,6 +107,7 @@ Rack::ActionLogger.configure do |config|
54
107
  config.emit_adapter = Rack::ActionLogger::EmitAdapter::FluentAdapter
55
108
  config.wrap_key = :message
56
109
  config.logger = Rails.logger
110
+ config.filters = Rails.application.config.filter_parameters
57
111
  end
58
112
  ```
59
113
 
@@ -63,31 +117,18 @@ If wrap_key is nil, the out put does not have parent key of wrap_key.
63
117
 
64
118
  ### Enable Request Log
65
119
 
66
- Add the following code to 'app/controllers/application_controller.rb'.
67
-
68
- ```ruby
69
- include Rack::ActionLogger::ControllerConcerns::RequestLog
70
- ```
71
-
72
- Request log should looks like this.
73
-
74
- ![request logs](docs/request_log.png)
75
-
76
- Request can be customized by creating new request log concern.
120
+ Request log is automatically enabled
77
121
 
122
+ Request can be customized by creating new class for rack_metrics configuration.
78
123
 
79
124
  ### Add Append Log
80
125
 
81
126
  Add the following code to any code on any times.
82
127
 
83
128
  ```ruby
84
- Rack::ActionLogger::Container.set_append_log({ value: 'ok' }, 'action.activities')
129
+ Rack::ActionLogger::Container.set_append_log({ value: 'ok' }, 'activities')
85
130
  ```
86
131
 
87
- Action log should looks like this.
88
-
89
- ![action log](docs/action_log.png)
90
-
91
132
  ### Override log attributes
92
133
 
93
134
  Overriden attributes are added to both request and append logs.
@@ -96,7 +137,18 @@ Overriden attributes are added to both request and append logs.
96
137
  Rack::ActionLogger::Container.merge_attributes({ user_id: 123 })
97
138
  ```
98
139
 
99
- ![attributed log](docs/attributed_log.png)
140
+ The append log is overrided by user_id attribute.
141
+
142
+ ```json
143
+ {
144
+ "message": {
145
+ "request_id": "150a6ac9-0fd9-4a23-a313-d18da1e35911",
146
+ "value": "with_tag",
147
+ "uer_id": 123,
148
+ "tag": "action.activities"
149
+ }
150
+ }
151
+ ```
100
152
 
101
153
  ### Logs out of request
102
154
 
@@ -111,7 +163,7 @@ class TestWorker < ApplicationController
111
163
 
112
164
  def perform(title, context)
113
165
  Rack::ActionLogger::Emitter.new.emit(context) do
114
- Rack::ActionLogger::Container.set_append_log({ title: title }, 'action.worker')
166
+ Rack::ActionLogger::Container.set_append_log({ title: title }, 'worker')
115
167
  p 'work: title=' + title
116
168
  end
117
169
  end
@@ -5,21 +5,38 @@ require 'logger'
5
5
 
6
6
  module Rack::ActionLogger
7
7
  class Configuration
8
+ DEFAULT_TAG_PREFIX = 'action'
9
+
8
10
  attr_accessor :emit_adapter
9
11
  attr_accessor :wrap_key
10
- attr_accessor :default_tag
11
12
  attr_accessor :tag_prefix
12
13
  attr_accessor :logger
14
+ attr_accessor :filters
15
+ attr_accessor :rack_request_blacklist
16
+ attr_accessor :pretty_print
17
+ attr_accessor :rack_metrics
13
18
 
14
19
  def initialize
15
20
  @emit_adapter = EmitAdapter::LoggerAdapter
16
- @tag_prefix = 'action'
21
+ @tag_prefix = DEFAULT_TAG_PREFIX
17
22
  @logger = Logger.new(STDOUT)
18
- @logger.progname = 'rack_action_logger'
23
+ @logger.progname = 'rack-action_logger'
24
+ @filters = ['password']
25
+ @rack_request_blacklist = [:request_headers, :response_headers, :response_json_body]
26
+ @pretty_print = true
27
+ @rack_metrics = Rack::ActionLogger::Metrics::RackMetrics
28
+ end
29
+
30
+ def tag_prefix
31
+ if @tag_prefix.to_s.empty?
32
+ Rack::ActionLogger.logger.error('tag_prefix should not be empty')
33
+ @tag_prefix = DEFAULT_TAG_PREFIX
34
+ end
35
+ @tag_prefix
19
36
  end
20
37
 
21
38
  def default_tag
22
- "#{@tag_prefix}.log"
39
+ [tag_prefix, 'log'].join('.')
23
40
  end
24
41
  end
25
42
  end
@@ -23,7 +23,7 @@ module Rack::ActionLogger
23
23
  store[:rack_action_logger_emit_started] ||= false
24
24
  end
25
25
 
26
- def set_append_log(hash, tag)
26
+ def set_append_log(hash, tag=nil)
27
27
  return unless is_valid_hash hash
28
28
  return unless is_valid_tag tag
29
29
  hash[:tag] = tag
@@ -43,7 +43,7 @@ module Rack::ActionLogger
43
43
  store[:rack_action_logger_attributes] ||= {}
44
44
  end
45
45
 
46
- def set_request_log(hash, tag)
46
+ def set_request_log(hash, tag=nil)
47
47
  return unless is_valid_hash hash
48
48
  return unless is_valid_tag tag
49
49
  hash[:tag] = tag
@@ -82,7 +82,7 @@ module Rack::ActionLogger
82
82
  end
83
83
 
84
84
  def is_valid_tag(tag)
85
- if tag.is_a? String
85
+ if tag.nil? || tag.is_a?(String)
86
86
  true
87
87
  else
88
88
  Rack::ActionLogger.logger.error("invalid tag: #{tag}")
@@ -7,9 +7,17 @@ module Rack::ActionLogger
7
7
 
8
8
  def call(env)
9
9
  Emitter.new.emit do
10
- @app.call(env)
10
+ status_code, headers, body = @app.call(env)
11
+ capture_rack_log(env, status_code, headers, body)
12
+ [status_code, headers, body]
11
13
  end
12
14
  end
13
15
 
16
+ def capture_rack_log(env, status_code, headers, body)
17
+ rack_metrics = Rack::ActionLogger.configuration.rack_metrics.new(env, status_code, headers, body)
18
+ Rack::ActionLogger::Container.set_request_log(rack_metrics.metrics, rack_metrics.tag_suffix)
19
+ Rack::ActionLogger::Container.merge_attributes({ request_id: rack_metrics.request_id })
20
+ end
21
+
14
22
  end
15
23
  end
@@ -1,10 +1,15 @@
1
+ require 'json'
1
2
  require 'rack/action_logger/emit_adapter/base'
2
3
 
3
4
  module Rack::ActionLogger::EmitAdapter
4
5
  class LoggerAdapter < Base
5
6
  def self.emit(hash)
6
7
  hash = wrap(hash)
7
- Rack::ActionLogger.logger.info(hash)
8
+ if Rack::ActionLogger.configuration.pretty_print
9
+ Rack::ActionLogger.logger.info(JSON.pretty_generate(hash))
10
+ else
11
+ Rack::ActionLogger.logger.info(hash)
12
+ end
8
13
  end
9
14
  end
10
15
  end
@@ -32,13 +32,24 @@ module Rack::ActionLogger
32
32
  def emit_request_log
33
33
  return unless (@container.get_request_log.is_a?(Hash) && @container.get_request_log != {})
34
34
  hash = @container.get_request_log.merge @container.get_attributes
35
+ hash = format_tag(hash)
35
36
  @emit_adapter.emit(hash)
36
37
  end
37
38
 
38
39
  def emit_append_logs
39
40
  @container.get_append_logs.each do |hash|
41
+ hash = format_tag(hash)
40
42
  @emit_adapter.emit(@container.get_attributes.merge!(hash))
41
43
  end
42
44
  end
45
+
46
+ def format_tag(hash)
47
+ if hash[:tag]
48
+ hash[:tag] = [Rack::ActionLogger.configuration.tag_prefix, hash[:tag]].join('.')
49
+ else
50
+ hash[:tag] = Rack::ActionLogger.configuration.default_tag
51
+ end
52
+ hash
53
+ end
43
54
  end
44
55
  end
@@ -0,0 +1,98 @@
1
+ require 'rack/action_logger'
2
+ require 'rack/mock'
3
+ require 'woothee'
4
+
5
+ module Rack::ActionLogger::Metrics
6
+ class RackMetrics
7
+ METRICS = [
8
+ :path, :method, :params, :request_headers, :status_code, :remote_ip, :user_agent, :device, :os, :browser,
9
+ :browser_version, :request_id, :response_headers, :response_json_body,
10
+ ]
11
+ RACK_TAG_PREFIX = 'rack'
12
+
13
+ attr_reader :status_code
14
+
15
+ def initialize(env, status_code, headers, body)
16
+ @env = env
17
+ @status_code = status_code
18
+ @headers = headers
19
+ @body = body
20
+ @request = Rack::Request.new(env)
21
+ @ua = Woothee.parse(@request.user_agent)
22
+ filters = Rack::ActionLogger.configuration.filters
23
+ @compiled_filters = Rack::ActionLogger::ParameterFiltering.compile(filters)
24
+ end
25
+
26
+ def tag_suffix
27
+ if @status_code == 404
28
+ tags = ['not_found']
29
+ else
30
+ tags = URI(path).path.split('/').reject { |c| c.empty? }
31
+ end
32
+ (Array(RACK_TAG_PREFIX) + tags).join('.')
33
+ end
34
+
35
+ def metrics
36
+ METRICS.inject({}) do |result, metric|
37
+ result[metric] = self.send(metric) unless
38
+ Rack::ActionLogger.configuration.rack_request_blacklist.include? metric
39
+ result
40
+ end
41
+ end
42
+
43
+ def path
44
+ @request.path
45
+ end
46
+
47
+ def method
48
+ @request.request_method
49
+ end
50
+
51
+ def params
52
+ Rack::ActionLogger::ParameterFiltering.apply_filter(@request.params, @compiled_filters)
53
+ end
54
+
55
+ def request_headers
56
+ @env.select { |v| v.start_with? 'HTTP_' }
57
+ end
58
+
59
+ def remote_ip
60
+ @request.ip
61
+ end
62
+
63
+ def user_agent
64
+ @request.user_agent
65
+ end
66
+
67
+ def device
68
+ @ua[:category]
69
+ end
70
+
71
+ def os
72
+ @ua[:os]
73
+ end
74
+
75
+ def browser
76
+ @ua[:name]
77
+ end
78
+
79
+ def browser_version
80
+ @ua[:version]
81
+ end
82
+
83
+ def request_id
84
+ @env['action_dispatch.request_id']
85
+ end
86
+
87
+ def response_headers
88
+ @headers
89
+ end
90
+
91
+ def response_json_body
92
+ response_bodies = []
93
+ @body.each { |part| response_bodies << part } if @body
94
+ result = JSON.parse(response_bodies.join('')) rescue {}
95
+ Rack::ActionLogger::ParameterFiltering.apply_filter(result, @compiled_filters)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,10 @@
1
+ require 'active_support'
2
+
3
+ module Rack::ActionLogger
4
+ module Metrics
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :RackMetrics
8
+ end
9
+ end
10
+
@@ -0,0 +1,31 @@
1
+ module Rack::ActionLogger
2
+ module ParameterFiltering
3
+ FILTERED = '[FILTERED]'.freeze # :nodoc:
4
+
5
+ class << self
6
+
7
+ def apply_filter(original_params, compiled_filters)
8
+ filtered_params = {}
9
+
10
+ original_params.each do |key, value|
11
+ if compiled_filters.any? { |r| key =~ r }
12
+ value = FILTERED
13
+ elsif value.is_a?(Hash)
14
+ value = apply_filter(value, compiled_filters)
15
+ elsif value.is_a?(Array)
16
+ value = value.map { |v| v.is_a?(Hash) ? apply_filter(v, compiled_filters) : v }
17
+ end
18
+
19
+ filtered_params[key] = value
20
+ end
21
+
22
+ filtered_params
23
+ end
24
+
25
+ def compile(filters)
26
+ filter_strings = filters.map(&:to_s)
27
+ filter_strings.map { |item| Regexp.compile(Regexp.escape(item)) }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module ActionLogger
3
- VERSION = '0.1.1'
3
+ VERSION = '0.1.2'
4
4
  end
5
5
  end
@@ -25,4 +25,6 @@ module Rack::ActionLogger
25
25
  autoload :Emitter, 'rack/action_logger/emitter'
26
26
  autoload :ControllerConcerns, 'rack/action_logger/controller_concerns'
27
27
  autoload :EmitAdapter, 'rack/action_logger/emit_adapter'
28
+ autoload :ParameterFiltering, 'rack/action_logger/parameter_filtering'
29
+ autoload :Metrics, 'rack/action_logger/metrics'
28
30
  end
@@ -6,9 +6,12 @@ require 'rack/action_logger/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'rack-action_logger'
8
8
  spec.version = Rack::ActionLogger::VERSION
9
+ spec.required_ruby_version = '>= 2.0.0'
10
+ spec.required_rubygems_version = '>= 1.3.5'
11
+ spec.rubygems_version = Gem::VERSION
9
12
  spec.authors = ['Koichi Ishida']
10
13
  spec.email = ['wapa5pow@gmail.com']
11
-
14
+ spec.date = Time.now.strftime('%Y-%m-%d')
12
15
  spec.summary = 'Rack::ActionLogger is a tool to log user activity'
13
16
  spec.description = 'Rack::ActionLogger is a tool to log user activity'
14
17
  spec.homepage = 'https://github.com/wapa5pow/rack-action_logger'
@@ -23,8 +26,10 @@ Gem::Specification.new do |spec|
23
26
 
24
27
  spec.add_dependency 'activesupport'
25
28
  spec.add_dependency 'fluent-logger', '~> 0.5'
29
+ spec.add_dependency 'woothee', '~> 1.4'
26
30
 
27
31
  spec.add_development_dependency 'bundler', '~> 1.13'
28
32
  spec.add_development_dependency 'rake', '~> 10.0'
29
33
  spec.add_development_dependency 'rspec', '~> 3.0'
34
+ spec.add_development_dependency 'rack-test', '~> 0.6.3'
30
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-action_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Ishida
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-16 00:00:00.000000000 Z
11
+ date: 2016-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: woothee
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.4'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack-test
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.6.3
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.6.3
83
111
  description: Rack::ActionLogger is a tool to log user activity
84
112
  email:
85
113
  - wapa5pow@gmail.com
@@ -104,13 +132,15 @@ files:
104
132
  - lib/rack/action_logger/container.rb
105
133
  - lib/rack/action_logger/context.rb
106
134
  - lib/rack/action_logger/controller_concerns.rb
107
- - lib/rack/action_logger/controller_concerns/request_log.rb
108
135
  - lib/rack/action_logger/emit_adapter.rb
109
136
  - lib/rack/action_logger/emit_adapter/base.rb
110
137
  - lib/rack/action_logger/emit_adapter/fluent_adapter.rb
111
138
  - lib/rack/action_logger/emit_adapter/logger_adapter.rb
112
139
  - lib/rack/action_logger/emit_adapter/null_adapter.rb
113
140
  - lib/rack/action_logger/emitter.rb
141
+ - lib/rack/action_logger/metrics.rb
142
+ - lib/rack/action_logger/metrics/rack_metrics.rb
143
+ - lib/rack/action_logger/parameter_filtering.rb
114
144
  - lib/rack/action_logger/version.rb
115
145
  - rack-action_logger.gemspec
116
146
  homepage: https://github.com/wapa5pow/rack-action_logger
@@ -125,12 +155,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
155
  requirements:
126
156
  - - ">="
127
157
  - !ruby/object:Gem::Version
128
- version: '0'
158
+ version: 2.0.0
129
159
  required_rubygems_version: !ruby/object:Gem::Requirement
130
160
  requirements:
131
161
  - - ">="
132
162
  - !ruby/object:Gem::Version
133
- version: '0'
163
+ version: 1.3.5
134
164
  requirements: []
135
165
  rubyforge_project:
136
166
  rubygems_version: 2.6.7
@@ -1,18 +0,0 @@
1
- require 'rack/action_logger/container'
2
-
3
- module Rack::ActionLogger::ControllerConcerns
4
- module RequestLog
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- before_action :set_request_log
9
- end
10
-
11
- def set_request_log
12
- Rack::ActionLogger::Container.set_request_log({ path_info: request.path_info, request_method: request.request_method }, 'action.request')
13
-
14
- request_id = Rails::VERSION::MAJOR >= 5 ? request.request_id : request.uuid
15
- Rack::ActionLogger::Container.merge_attributes({ request_id: request_id })
16
- end
17
- end
18
- end