istox_gruf 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +246 -0
  3. data/CODE_OF_CONDUCT.md +46 -0
  4. data/README.md +544 -0
  5. data/bin/gruf +29 -0
  6. data/lib/gruf.rb +50 -0
  7. data/lib/gruf/cli/executor.rb +99 -0
  8. data/lib/gruf/client.rb +217 -0
  9. data/lib/gruf/client/error.rb +66 -0
  10. data/lib/gruf/client/error_factory.rb +105 -0
  11. data/lib/gruf/configuration.rb +137 -0
  12. data/lib/gruf/controllers/base.rb +102 -0
  13. data/lib/gruf/controllers/request.rb +121 -0
  14. data/lib/gruf/controllers/service_binder.rb +117 -0
  15. data/lib/gruf/error.rb +230 -0
  16. data/lib/gruf/errors/debug_info.rb +56 -0
  17. data/lib/gruf/errors/field.rb +56 -0
  18. data/lib/gruf/errors/helpers.rb +44 -0
  19. data/lib/gruf/hooks/base.rb +34 -0
  20. data/lib/gruf/hooks/executor.rb +47 -0
  21. data/lib/gruf/hooks/registry.rb +159 -0
  22. data/lib/gruf/instrumentable_grpc_server.rb +64 -0
  23. data/lib/gruf/integrations/rails/railtie.rb +10 -0
  24. data/lib/gruf/interceptors/active_record/connection_reset.rb +48 -0
  25. data/lib/gruf/interceptors/authentication/basic.rb +87 -0
  26. data/lib/gruf/interceptors/base.rb +53 -0
  27. data/lib/gruf/interceptors/client_interceptor.rb +125 -0
  28. data/lib/gruf/interceptors/context.rb +56 -0
  29. data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +61 -0
  30. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb +41 -0
  31. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb +43 -0
  32. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb +48 -0
  33. data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +225 -0
  34. data/lib/gruf/interceptors/instrumentation/statsd.rb +82 -0
  35. data/lib/gruf/interceptors/registry.rb +161 -0
  36. data/lib/gruf/interceptors/server_interceptor.rb +34 -0
  37. data/lib/gruf/interceptors/timer.rb +85 -0
  38. data/lib/gruf/loggable.rb +30 -0
  39. data/lib/gruf/logging.rb +53 -0
  40. data/lib/gruf/outbound/request_context.rb +71 -0
  41. data/lib/gruf/response.rb +71 -0
  42. data/lib/gruf/serializers/errors/base.rb +57 -0
  43. data/lib/gruf/serializers/errors/json.rb +43 -0
  44. data/lib/gruf/server.rb +294 -0
  45. data/lib/gruf/synchronized_client.rb +97 -0
  46. data/lib/gruf/timer.rb +78 -0
  47. data/lib/gruf/version.rb +20 -0
  48. metadata +203 -0
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Interceptors
20
+ module Instrumentation
21
+ ##
22
+ # Adds increment and timing stats to gRPC routes, pushing data to StatsD
23
+ #
24
+ class Statsd < Gruf::Interceptors::ServerInterceptor
25
+ ##
26
+ # Push data to StatsD, only doing so if a client is set
27
+ #
28
+ def call
29
+ unless client
30
+ Gruf.logger.error 'Statsd module loaded, but no client configured!'
31
+ return yield
32
+ end
33
+
34
+ client.increment(route_key)
35
+
36
+ result = Gruf::Interceptors::Timer.time do
37
+ yield
38
+ end
39
+
40
+ client.increment("#{route_key}.#{postfix(result.successful?)}")
41
+ client.timing(route_key, result.elapsed)
42
+
43
+ raise result.message unless result.successful?
44
+
45
+ result.message
46
+ end
47
+
48
+ private
49
+
50
+ ##
51
+ # @param [Boolean] successful Whether or not the request was successful
52
+ # @return [String] The appropriate postfix for the key dependent on response status
53
+ #
54
+ def postfix(successful)
55
+ successful ? 'success' : 'failure'
56
+ end
57
+
58
+ ##
59
+ # @return [String] Return a composed route key that is used in the statsd metric
60
+ #
61
+ def route_key
62
+ "#{key_prefix}#{request.method_name}"
63
+ end
64
+
65
+ ##
66
+ # @return [String] Return the sanitized key prefix for the statsd metric key
67
+ #
68
+ def key_prefix
69
+ prefix = options.fetch(:prefix, '').to_s
70
+ prefix.empty? ? '' : "#{prefix}."
71
+ end
72
+
73
+ ##
74
+ # @return [::Statsd] Return the given StatsD client
75
+ #
76
+ def client
77
+ @client ||= options.fetch(:client, nil)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Interceptors
20
+ ##
21
+ # Handles registration of interceptors
22
+ #
23
+ class Registry
24
+ class InterceptorNotFoundError < StandardError; end
25
+
26
+ def initialize
27
+ @registry = []
28
+ end
29
+
30
+ ##
31
+ # Add an interceptor to the registry
32
+ #
33
+ # @param [Class] interceptor_class The class of the interceptor to add
34
+ # @param [Hash] options A hash of options to pass into the interceptor during initialization
35
+ #
36
+ def use(interceptor_class, options = {})
37
+ interceptors_mutex do
38
+ @registry << {
39
+ klass: interceptor_class,
40
+ options: options
41
+ }
42
+ end
43
+ end
44
+
45
+ ##
46
+ # Remove an interceptor from the registry
47
+ #
48
+ # @param [Class] interceptor_class The interceptor class to remove
49
+ # @raise [InterceptorNotFoundError] if the interceptor is not found
50
+ #
51
+ def remove(interceptor_class)
52
+ pos = @registry.find_index { |opts| opts.fetch(:klass, '') == interceptor_class }
53
+ raise InterceptorNotFoundError if pos.nil?
54
+
55
+ @registry.delete_at(pos)
56
+ end
57
+
58
+ ##
59
+ # Insert an interceptor before another specified interceptor
60
+ #
61
+ # @param [Class] before_class The interceptor to insert before
62
+ # @param [Class] interceptor_class The class of the interceptor to add
63
+ # @param [Hash] options A hash of options to pass into the interceptor during initialization
64
+ # @raise [InterceptorNotFoundError] if the before interceptor is not found
65
+ #
66
+ def insert_before(before_class, interceptor_class, options = {})
67
+ interceptors_mutex do
68
+ pos = @registry.find_index { |opts| opts.fetch(:klass, '') == before_class }
69
+ raise InterceptorNotFoundError if pos.nil?
70
+
71
+ @registry.insert(
72
+ pos,
73
+ klass: interceptor_class,
74
+ options: options
75
+ )
76
+ end
77
+ end
78
+
79
+ ##
80
+ # Insert an interceptor after another specified interceptor
81
+ #
82
+ # @param [Class] after_class The interceptor to insert after
83
+ # @param [Class] interceptor_class The class of the interceptor to add
84
+ # @param [Hash] options A hash of options to pass into the interceptor during initialization
85
+ # @raise [InterceptorNotFoundError] if the after interceptor is not found
86
+ #
87
+ def insert_after(after_class, interceptor_class, options = {})
88
+ interceptors_mutex do
89
+ pos = @registry.find_index { |opts| opts.fetch(:klass, '') == after_class }
90
+ raise InterceptorNotFoundError if pos.nil?
91
+
92
+ @registry.insert(
93
+ (pos + 1),
94
+ klass: interceptor_class,
95
+ options: options
96
+ )
97
+ end
98
+ end
99
+
100
+ ##
101
+ # Return a list of the interceptor classes in the registry in their execution order
102
+ #
103
+ # @return [Array<Class>]
104
+ #
105
+ def list
106
+ interceptors_mutex do
107
+ @registry.map { |h| h[:klass] }
108
+ end
109
+ end
110
+
111
+ ##
112
+ # Load and return all interceptors for the given request
113
+ #
114
+ # @param [Gruf::Controllers::Request] request
115
+ # @param [Gruf::Error] error
116
+ # @return [Array<Gruf::Interceptors::Base>]
117
+ #
118
+ def prepare(request, error)
119
+ is = []
120
+ interceptors_mutex do
121
+ @registry.each do |o|
122
+ is << o[:klass].new(request, error, o[:options])
123
+ end
124
+ end
125
+ is
126
+ end
127
+
128
+ ##
129
+ # Clear the registry
130
+ #
131
+ def clear
132
+ interceptors_mutex do
133
+ @registry = []
134
+ end
135
+ end
136
+
137
+ ##
138
+ # @return [Integer] The number of interceptors currently loaded
139
+ #
140
+ def count
141
+ interceptors_mutex do
142
+ @registry ||= []
143
+ @registry.count
144
+ end
145
+ end
146
+
147
+ private
148
+
149
+ ##
150
+ # Handle mutations to the interceptor registry in a thread-safe manner
151
+ #
152
+ def interceptors_mutex(&block)
153
+ @interceptors_mutex ||= begin
154
+ require 'monitor'
155
+ Monitor.new
156
+ end
157
+ @interceptors_mutex.synchronize(&block)
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Interceptors
20
+ ##
21
+ # Intercepts server requests
22
+ #
23
+ class ServerInterceptor < Base
24
+ include Gruf::Errors::Helpers
25
+
26
+ ##
27
+ # Call the interceptor
28
+ #
29
+ def call
30
+ raise NotImplementedError
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Interceptors
20
+ ##
21
+ # Utility class that can be used by interceptors to time requests
22
+ #
23
+ class Timer
24
+ ##
25
+ # Represents a timed result for an interceptor
26
+ #
27
+ class Result
28
+ attr_reader :message
29
+ attr_reader :elapsed
30
+
31
+ ##
32
+ # @param [Object] message The protobuf message
33
+ # @param [Float] elapsed The elapsed time of the request
34
+ # @param [Boolean] successful If the request was successful
35
+ #
36
+ def initialize(message, elapsed, successful)
37
+ @message = message
38
+ @elapsed = elapsed.to_f
39
+ @successful = successful ? true : false
40
+ end
41
+
42
+ ##
43
+ # @return [Boolean] True if this was a successful request
44
+ #
45
+ def successful?
46
+ @successful
47
+ end
48
+
49
+ ##
50
+ # @return [String] The name of the message class
51
+ #
52
+ def message_class_name
53
+ @message.class.name
54
+ end
55
+
56
+ ##
57
+ # Return the execution time rounded to a specified precision
58
+ #
59
+ # @param [Integer] precision The amount of decimal places to round to
60
+ # @return [Float] The execution time rounded to the appropriate decimal point
61
+ #
62
+ def elapsed_rounded(precision: 2)
63
+ @elapsed.to_f.round(precision)
64
+ end
65
+ end
66
+
67
+ ##
68
+ # Time a given code block and return a Timer::Result object
69
+ #
70
+ # @return [Gruf::Interceptors::Timer::Result]
71
+ #
72
+ def self.time
73
+ start_time = Time.now
74
+ message = yield
75
+ end_time = Time.now
76
+ elapsed = (end_time - start_time) * 1000.0
77
+ Result.new(message, elapsed, true)
78
+ rescue GRPC::BadStatus => e
79
+ end_time = Time.now
80
+ elapsed = (end_time - start_time) * 1000.0
81
+ Result.new(e, elapsed, false)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ ##
20
+ # Mixin that allows any Gruf class to have easy access to the Gruf logger
21
+ #
22
+ module Loggable
23
+ ##
24
+ # @return [Logger] The set logger for Gruf
25
+ #
26
+ def logger
27
+ Gruf.logger
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ ##
20
+ # Handles internal gruf logging requests
21
+ #
22
+ module Logger
23
+ ##
24
+ # Return the current Gruf logger
25
+ #
26
+ # @return [Logger]
27
+ #
28
+ def logger
29
+ Gruf.logger
30
+ end
31
+ end
32
+
33
+ ##
34
+ # Handles grpc internal logging requests
35
+ #
36
+ module GrpcLogger
37
+ ##
38
+ # Return the current Gruf gRPC core logger
39
+ #
40
+ # @return [Logger]
41
+ #
42
+ def logger
43
+ Gruf.grpc_logger
44
+ end
45
+ end
46
+ end
47
+
48
+ ##
49
+ # Implements gruf's gRPC logger into the gRPC library logger
50
+ #
51
+ module GRPC
52
+ extend Gruf::GrpcLogger
53
+ end