orange_tap 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44504ce4b47d41f26a788f14a8ca53379ebaaa97e2f50e7e45b1af6c833a20f2
4
- data.tar.gz: 5f4b54c1ce9984c1cc42e9eed43231d56be3f0f63d25d085d9236b7a17cfd652
3
+ metadata.gz: ca009ebd31ae0ff1849d7975d602f1f87dccbada30458cd4943e6a526aa35647
4
+ data.tar.gz: 662aa3e960659b36c5febb1b1f59e2d39d2010146a208584155f7e860206b77a
5
5
  SHA512:
6
- metadata.gz: 1b418033fa327fc2b95866552f64316e0d642d711578df92200c7736efcd7740d5a314d2047f531aced963b5cdce507f1a90e7257676bd45385ab0354bb27f0c
7
- data.tar.gz: d42a4780a31e34c525d1471470634f1c5584fbdc722eb15b59cf56a628354b4de0c0fcddd3af85914c0f73489ef9e465bd53148eb675c60be18efb83ef11d765
6
+ metadata.gz: bdd6c3f5b6158f7df4dd462c4aa6be2b38bd060d5a9c26596487c93510b03d3c9259efbeee60d1d5c960060f05265608b56e1edea922a3de534414ef5578934f
7
+ data.tar.gz: bbc112874962e22531f59e7fca2b5569831fbb956a690692c24f219fb32c67295d48aaf632ecb276f2ac6c22e4122e3992d8942f9976a96a9e6f5238a044b7f8
data/README.md CHANGED
@@ -115,6 +115,33 @@ tape.open("checkout-flow")
115
115
  tape.stop
116
116
  ```
117
117
 
118
+ ### `record`: measure a block with config and error handling taken care of
119
+
120
+ `OrangeTap.record` wraps a single session for the common "measure this block
121
+ once" case (e.g. a Rails `around_action`). Compared to `open`, it handles two
122
+ things every caller otherwise re-implements by hand:
123
+
124
+ - **`config_overrides`** are applied for the duration of the block and
125
+ restored afterwards, *even on error*. `OrangeTap.config` is a process-global
126
+ singleton, so a leaked `trace_all_app_methods = true` would keep every later
127
+ session in the heaviest mode — `record` guarantees it is reset.
128
+ - **`on_output`** is called with the written JSON path in an `ensure`, so you
129
+ receive the path on **both success and failure**. (Block-form `open` cannot
130
+ return the path when the block raises.) The trace file is written either way,
131
+ since the worker drains on `stop`.
132
+
133
+ ```ruby
134
+ OrangeTap.record(
135
+ "checkout-flow",
136
+ trace_all_app_methods: true, # applied, then restored
137
+ on_output: ->(path) { Rails.logger.info("OrangeTap: #{path}") }
138
+ ) do
139
+ MyApp.handle(request)
140
+ end
141
+ # => output path on success; the original error is re-raised on failure
142
+ # (an on_output that itself raises is swallowed so it never masks it)
143
+ ```
144
+
118
145
  Other registration entry points:
119
146
 
120
147
  ```ruby
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OrangeTap
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/orange_tap.rb CHANGED
@@ -67,4 +67,52 @@ module OrangeTap
67
67
  raise
68
68
  end
69
69
  end
70
+
71
+ # A batteries-included wrapper around a single session, meant for the
72
+ # common "measure this block once" case (e.g. a Rails around_action):
73
+ #
74
+ # OrangeTap.record("checkout", trace_all_app_methods: true,
75
+ # on_output: ->(path) { Rails.logger.info(path) }) { do_work }
76
+ #
77
+ # It handles the two things every caller otherwise has to re-implement by
78
+ # hand around #open:
79
+ #
80
+ # * config_overrides are applied for the duration of the block and restored
81
+ # afterwards, even on error. OrangeTap.config is a process-global
82
+ # singleton, so a leaked `trace_all_app_methods = true` would keep every
83
+ # later session in the heaviest mode; this guarantees it is reset.
84
+ # * on_output is called with the written JSON path in the ensure, so the
85
+ # path is delivered on BOTH success and failure. (Block form #open cannot
86
+ # return the path when the block raises.) The trace file is written either
87
+ # way, since the worker drains on stop.
88
+ #
89
+ # Returns the output path on success; re-raises the original error on
90
+ # failure (an on_output that raises is swallowed so it never masks it).
91
+ def record(name = nil, on_output: nil, **config_overrides)
92
+ previous = config_overrides.to_h { |key, _| [key, config.public_send(key)] }
93
+ config_overrides.each { |key, value| config.public_send("#{key}=", value) }
94
+
95
+ tape = new
96
+ tape.open(name)
97
+ path = nil
98
+ begin
99
+ yield
100
+ path = tape.stop
101
+ rescue Exception # rubocop:disable Lint/RescueException
102
+ path = begin
103
+ tape.stop
104
+ rescue StandardError
105
+ nil
106
+ end
107
+ raise
108
+ ensure
109
+ previous.each { |key, value| config.public_send("#{key}=", value) }
110
+ begin
111
+ on_output&.call(path)
112
+ rescue StandardError
113
+ nil
114
+ end
115
+ end
116
+ path
117
+ end
70
118
  end
data/sig/orange_tap.rbs CHANGED
@@ -1,4 +1,48 @@
1
1
  module OrangeTap
2
2
  VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
3
+
4
+ class Error < StandardError
5
+ end
6
+
7
+ class AlreadyOpenError < Error
8
+ end
9
+
10
+ class NotOpenError < Error
11
+ end
12
+
13
+ class UntraceableMethodError < Error
14
+ end
15
+
16
+ # A Method/UnboundMethod, or a "Foo#bar" / "Foo.bar" notation String.
17
+ type method_obj = Method | UnboundMethod | String
18
+
19
+ def self.new: (**untyped opts) -> Session
20
+
21
+ def self.default_registry: () -> MethodRegistry
22
+
23
+ def self.config: () -> Config
24
+
25
+ def self.trace_method: (*method_obj method_objs) -> void
26
+
27
+ def self.untrace_method: (*method_obj method_objs) -> void
28
+
29
+ def self.trace_all_instance_methods: (Class klass) -> void
30
+
31
+ # Block form returns the output path; blockless form returns the Session.
32
+ def self.open: (?String? name) ?{ () -> void } -> (String | Session)
33
+
34
+ # Runs the block in a single session, applying config_overrides for its
35
+ # duration (restored afterwards, even on error) and delivering the output
36
+ # path to on_output on both success and failure. Returns the path on success.
37
+ def self.record: (?String? name, ?on_output: (^(String?) -> void)?, **untyped config_overrides) { () -> void } -> String?
38
+
39
+ class Config
40
+ attr_accessor output_dir: String
41
+ attr_accessor service_name: String
42
+ attr_accessor otel_converter: untyped
43
+ attr_accessor trace_c_methods: bool
44
+ attr_accessor trace_all_app_methods: bool
45
+
46
+ def initialize: () -> void
47
+ end
4
48
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orange_tap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Uchio Kondo