vigiles 0.1.0.pre.beta8 → 0.1.0.pre.beta10

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
  SHA256:
3
- metadata.gz: 9ae2f2c7a8b3a0642d0fb228264821c882b9b98cf7a59380dcf139e1a514221c
4
- data.tar.gz: 7ca651c0579f55907094ade6d43825cae72627fef6c8e995fd621d7f94e9acc4
3
+ metadata.gz: cceedc075f3779ec0c77cc04a35058734cd2d2396ea67b95c6b1117763caa719
4
+ data.tar.gz: 3ea39ba08de23e8b51b66bc0e4b4cc38ca52e467ccdf671d49cdb52e7ff98453
5
5
  SHA512:
6
- metadata.gz: a942ca1c61aefdb02f843b7d3defd046ebce9935b47d406e8193c2c54b7befd360b19f974618f24f42c23278e8c313be513d25b68fece32985d2272f504b8c2e
7
- data.tar.gz: 2a70d2be56a5c86fa4f30f881b6b9002e6967cfe6cd04339f1bb4f70f1a6f8bd28b6ae34281a19b5504ad82a594fa8b0660591ff0ab28e9ad3fdd94214c26d78
6
+ metadata.gz: a884ac729b71b8351aae48ce0515d2a803f6358f03d03cc3efbbdb5304c2d811de6401eea203329fbea433c9d3896d77fc2f25bb0947226a689c1e466f64b8fd
7
+ data.tar.gz: 8a2b120ce179764649389ce270a45015e8e67379f70cb40035cef4f58cf321c6e81a376b62482842825599d7c101fec4ee69aa60aa9889146f6ed2f1daa15297
@@ -35,12 +35,21 @@ module Vigiles
35
35
  const :url, T.any(URI::HTTPS, URI::HTTP)
36
36
  const :id, String
37
37
 
38
+ sig { params(header_key: String).returns(String) }
39
+ private_class_method def self.best_effort_unfuck_http_header(header_key)
40
+ (header_key.starts_with?("HTTP_") ? T.must(header_key[5..]) : header_key)
41
+ .split(/_/)
42
+ .map(&:titlecase)
43
+ .join("-")
44
+ end
45
+
38
46
  sig { params(request: ActionDispatch::Request).returns(Request) }
39
47
  def self.from(request)
40
48
  preferred_headers = Vigiles.spec.request_headers
41
49
  available_headers = request.original_headers
42
50
  recorded_headers = (available_headers if preferred_headers.empty?)
43
- recorded_headers ||= preferred_headers.to_h { |h| [h, available_headers[h]] }
51
+ recorded_headers ||= preferred_headers.to_h { [_1, available_headers[_1]] }
52
+ unfucked_headers = recorded_headers.transform_keys { best_effort_unfuck_http_header _1 }
44
53
 
45
54
  Request.new(
46
55
  content_type: request.content_type || (raise InvalidParameterError, "content_type"),
@@ -48,7 +57,7 @@ module Vigiles
48
57
  timestamp: DateTime.now,
49
58
  remote_ip: IPAddr.new(request.remote_ip),
50
59
  protocol: request.protocol,
51
- headers: recorded_headers,
60
+ headers: unfucked_headers,
52
61
  origin: request.origin || "unknown_origin_url",
53
62
  payload: request.body.read,
54
63
  http_method: Types::HttpMethod.deserialize(request.method),
@@ -27,48 +27,5 @@ module Vigiles
27
27
 
28
28
  recorder.record(req:, res:)
29
29
  end
30
-
31
- sig do
32
- params(
33
- request: Request,
34
- response: Response,
35
- metadata: Metadata,
36
- extras: Extras
37
- )
38
- .returns(T.nilable(Conversation))
39
- end
40
- private_class_method def self.record_json_conversation(request:, response:, metadata:, extras:)
41
- Conversation.create!(
42
- request_content_type: request.content_type,
43
- request_user_agent: request.user_agent,
44
- request_timestamp: request.timestamp,
45
- request_remote_ip: request.remote_ip,
46
- request_protocol: request.protocol,
47
- request_headers: request.headers,
48
- request_origin: request.origin,
49
- request_payload: request.payload,
50
- request_method: request.http_method.serialize,
51
- request_path: request.path,
52
- request_url: request.url,
53
- request_id: request.id,
54
- response_content_type: response.content_type,
55
- response_headers: response.headers,
56
- response_payload: response.payload,
57
- response_status: response.status
58
- )
59
- rescue => e
60
- end
61
-
62
- sig { params(request: Request, response: Response, metadata: Metadata, extras: Extras).returns(T.nilable(Conversation)) }
63
- private_class_method def self.record_html_conversation(request:, response:, metadata:, extras:); end
64
-
65
- sig { params(request: Request, response: Response, metadata: Metadata, extras: Extras).returns(T.nilable(Conversation)) }
66
- private_class_method def self.record_conversation_with_unknown_content_type(
67
- request:,
68
- response:,
69
- metadata:,
70
- extras:
71
- )
72
- end
73
30
  end
74
31
  end
@@ -25,7 +25,6 @@ module Vigiles
25
25
 
26
26
  response = Response.from(res)
27
27
  request = Request.from(req)
28
-
29
28
  Conversation.create!(
30
29
  request_content_type: request.content_type,
31
30
  request_user_agent: request.user_agent,
@@ -2,15 +2,25 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "logger"
5
+
5
6
  module Vigiles
6
7
  module Middleware
7
8
  class RecordConversation
8
- sig { params(app: T.untyped).void }
9
- def initialize(app)
10
- @app = app
9
+ sig { returns(Vigiles::Options) }
10
+ attr_reader :options
11
+
12
+ delegate \
13
+ :capture_exception,
14
+ :logger,
15
+ to: :options
16
+
17
+ sig { params(app: T.untyped, options: Vigiles::Options).void }
18
+ def initialize(app, options=Vigiles::Options.make_default_options)
19
+ @app = app
20
+ @options = options
11
21
  end
12
22
 
13
- sig { params(env: T.untyped).returns(T.untyped) }
23
+ sig { params(env: T::Hash[T.untyped, T.untyped]).returns(T.untyped) }
14
24
  def call(env)
15
25
  req = ActionDispatch::Request.new(env)
16
26
  record_conversation(req) do
@@ -20,11 +30,29 @@ module Vigiles
20
30
 
21
31
  sig { params(req: ActionDispatch::Request, blk: T.proc.returns(T.untyped)).returns(T.untyped) }
22
32
  private def record_conversation(req, &blk)
23
- res = Rack::Response[*blk.call]
24
- Vigiles.maybe_record_conversation(req:, res:)
25
- res.to_a
26
- ensure
27
- res.to_a
33
+ rack_response = blk.call
34
+ begin
35
+ res = Rack::Response[*rack_response]
36
+ convo = Vigiles.maybe_record_conversation(req:, res:)
37
+ logger.info \
38
+ "[vigiles] conversation recorder: " \
39
+ "conversation=#{convo.nil? ? "not_recorded" : convo.id} " \
40
+ "request=#{req.request_id}"
41
+ rescue => e
42
+ capture_exception.call(e)
43
+ logger.warn \
44
+ "[vigiles] conversation recorder error: " \
45
+ "error_message=#{e.message} " \
46
+ "error_class=#{e.class}"
47
+ ensure
48
+ # no matter what happens we shouldn't prevent the rack
49
+ # response from being returned. at this point, the only
50
+ # thing that could throw execution into this branch is
51
+ # an exception when the `capture_exception` proc is
52
+ # invoked.
53
+ rack_response
54
+ end
55
+ rack_response
28
56
  end
29
57
  end
30
58
  end
@@ -0,0 +1,19 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "logger"
5
+
6
+ module Vigiles
7
+ class Options < T::Struct
8
+ const :capture_exception, T.proc.params(a0: StandardError).void
9
+ const :logger, ::Logger
10
+
11
+ sig { returns(Options) }
12
+ def self.make_default_options
13
+ Options.new(
14
+ logger: T.unsafe(Rails).logger, # you should be using this within rails.
15
+ capture_exception: ->(e) { e } # a no-op exception capturer.
16
+ )
17
+ end
18
+ end
19
+ end
data/lib/vigiles/spec.rb CHANGED
@@ -3,9 +3,9 @@
3
3
 
4
4
  module Vigiles
5
5
  class Spec < T::Struct
6
- const :request_content_types, T::Set[String]
7
- const :request_headers, T::Set[String]
8
- const :recorders, T::Hash[String, ConversationRecorder]
6
+ const :request_content_types, T::Set[String]
7
+ const :request_headers, T::Set[String]
8
+ const :recorders, T::Hash[String, ConversationRecorder]
9
9
 
10
10
  sig { returns(Spec) }
11
11
  def self.make_default_spec
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Vigiles
5
- VERSION = "0.1.0-beta8"
5
+ VERSION = "0.1.0-beta10"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vigiles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.beta8
4
+ version: 0.1.0.pre.beta10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yaw Boakye
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-24 00:00:00.000000000 Z
11
+ date: 2024-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -225,6 +225,7 @@ files:
225
225
  - lib/vigiles/conversation_recorders/application_json.rb
226
226
  - lib/vigiles/conversation_recorders/unknown.rb
227
227
  - lib/vigiles/middleware/record_conversation.rb
228
+ - lib/vigiles/options.rb
228
229
  - lib/vigiles/spec.rb
229
230
  - lib/vigiles/types.rb
230
231
  - lib/vigiles/utilities/uri.rb