lab_coat 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +11 -6
- data/lib/lab_coat/experiment.rb +13 -12
- data/lib/lab_coat/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c1c5580cec0ec677137fcbf23a90291fab80564c955a1d8b10fb48903f1f43b
|
4
|
+
data.tar.gz: 15540d166b6a0d6098c07979efc8b780ecebb26d5059ac3db1217489e2448e06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c84bde55abd4974f068a802f181552111d847c3eeca07e28046fe3492919ba25a12fdefb10ac547bc22fbce90c1785fa01d73084db769f51ebe55993d52b2cc9
|
7
|
+
data.tar.gz: 128f1a14f2a2ec4f370d40d5c5b147d35b26abd75f558d5f19755fb71e82cfe8aad4de8673835a82c9b12f21088642ea346aa3bba4d29cdcc7d334a15b4622db
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## [0.1.4] - Unreleased
|
2
|
+
- Remove the arity check, it's not very intuitive
|
3
|
+
- Adds a `@context` that gets set at runtime and reset after each run. This is a much simpler way for methods to access a shared runtime context that can be set per `run!`.
|
4
|
+
|
1
5
|
## [0.1.3] - 2024-04-17
|
2
6
|
- `Experiment` now enforces arity at runtime for the `#enabled?`, `control`, and `candidate` methods.
|
3
7
|
|
data/README.md
CHANGED
@@ -57,7 +57,7 @@ See the [`Experiment`](lib/lab_coat/experiment.rb) class for more details.
|
|
57
57
|
|`publish!`|This is not _technically_ required, but `Experiments` are not useful unless you can analyze the results. Override this method to record the `Result` however you wish.|
|
58
58
|
|
59
59
|
> [!IMPORTANT]
|
60
|
-
> The `#run!` method accepts arbitrary arguments and
|
60
|
+
> The `#run!` method accepts arbitrary key word arguments and stores them in an instance variable called `@context` in case you need to provide data at runtime. You can access the runtime context via `@context` or `context`. The runtime context **is reset** after each run.
|
61
61
|
|
62
62
|
#### Additional methods
|
63
63
|
|
@@ -88,13 +88,16 @@ You might want to `publish!` all experiments in a consistent way so that you can
|
|
88
88
|
# application_experiment.rb
|
89
89
|
class ApplicationExperiment < LabCoat::Experiment
|
90
90
|
def publish!(result)
|
91
|
-
payload = result.to_h.merge(
|
91
|
+
payload = result.to_h.merge(
|
92
|
+
user_id: @user.id, # e.g. something from the `Experiment` state
|
93
|
+
build_number: context.version # e.g. something from the runtime context
|
94
|
+
)
|
92
95
|
YourO11yService.track_experiment_result(payload)
|
93
96
|
end
|
94
97
|
end
|
95
98
|
```
|
96
99
|
|
97
|
-
You might have a common way to enable experiments such as a feature flag system and/or common guards you want to enforce application wide. These might come from a mix of services
|
100
|
+
You might have a common way to enable experiments such as a feature flag system and/or common guards you want to enforce application wide. These might come from a mix of services, the `Experiment`'s state, or the runtime `context`.
|
98
101
|
|
99
102
|
```ruby
|
100
103
|
# application_experiment.rb
|
@@ -123,6 +126,8 @@ end
|
|
123
126
|
|
124
127
|
You don't have to create an `Observation` yourself; that happens automatically when you call `Experiment#run!`. The control and candidate `Observations` are packaged into a `Result` and [passed to `Experiment#publish!`](#publish-the-result).
|
125
128
|
|
129
|
+
The `run!` method accepts arbitrary keyword arguments, to allow you to set runtime context for the specific run of the experiment. You can access this `Hash` via the `context` reader method, or directly via the `@context` instance variable.
|
130
|
+
|
126
131
|
|Attribute|Description|
|
127
132
|
|---|---|
|
128
133
|
|`duration`|The duration of the run represented as a `Benchmark::Tms` object.|
|
@@ -180,14 +185,14 @@ A `Result` represents a single run of an `Experiment`.
|
|
180
185
|
|`matched?`|Whether or not the `control` and `candidate` match, as defined by `Experiment#compare`|
|
181
186
|
|`to_h`|A hash representation of the `Result`. Useful for publishing and/or reporting.|
|
182
187
|
|
183
|
-
The `Result` is passed to your implementation of `#publish!` when an `Experiment` is finished running. The `to_h` method on a Result is a good place to start and might be sufficient for most experiments.
|
188
|
+
The `Result` is passed to your implementation of `#publish!` when an `Experiment` is finished running. The `to_h` method on a Result is a good place to start and might be sufficient for most experiments. You might want to `merge` additional data such as the runtime `context` or other state if you find that relevant for analysis.
|
184
189
|
|
185
190
|
```ruby
|
186
191
|
# your_experiment.rb
|
187
192
|
def publish!(result)
|
188
193
|
return if result.ignored?
|
189
194
|
|
190
|
-
puts result.to_h
|
195
|
+
puts result.to_h.merge(run_context: context)
|
191
196
|
end
|
192
197
|
```
|
193
198
|
|
@@ -276,7 +281,7 @@ end
|
|
276
281
|
```
|
277
282
|
|
278
283
|
> [!WARNING]
|
279
|
-
> Be careful when using `Observation` instances without an `Experiment` set. Some methods like `#publishable_value` and `#slug` depend on an `experiment` and may raise an error when called.
|
284
|
+
> Be careful when using `Observation` instances without an `Experiment` set. Some methods like `#publishable_value` and `#slug` depend on an `experiment` and may raise an error or return unexpected values when called without one.
|
280
285
|
|
281
286
|
## Development
|
282
287
|
|
data/lib/lab_coat/experiment.rb
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
module LabCoat
|
4
4
|
# A base experiment class meant to be subclassed to define various experiments.
|
5
5
|
class Experiment
|
6
|
-
attr_reader :name
|
6
|
+
attr_reader :name, :context
|
7
7
|
|
8
8
|
def initialize(name)
|
9
9
|
@name = name
|
10
|
+
@context = {}
|
10
11
|
end
|
11
12
|
|
12
13
|
# Override this method to control whether or not the experiment runs.
|
@@ -18,13 +19,13 @@ module LabCoat
|
|
18
19
|
# Override this method to define the existing aka "control" behavior. This method is always run, even when
|
19
20
|
# `enabled?` is false.
|
20
21
|
# @return [Object] Anything.
|
21
|
-
def control
|
22
|
+
def control
|
22
23
|
raise InvalidExperimentError, "`#control` must be implemented in your Experiment class."
|
23
24
|
end
|
24
25
|
|
25
26
|
# Override this method to define the new aka "candidate" behavior. Only run if the experiment is enabled.
|
26
27
|
# @return [Object] Anything.
|
27
|
-
def candidate
|
28
|
+
def candidate
|
28
29
|
raise InvalidExperimentError, "`#candidate` must be implemented in your Experiment class."
|
29
30
|
end
|
30
31
|
|
@@ -59,25 +60,25 @@ module LabCoat
|
|
59
60
|
|
60
61
|
# Runs the control and candidate and publishes the result. Always returns the result of `control`.
|
61
62
|
# @param context [Hash] Any data needed at runtime.
|
62
|
-
def run!(
|
63
|
-
|
63
|
+
def run!(**context)
|
64
|
+
# Set the context for this run.
|
65
|
+
@context = context
|
64
66
|
|
65
67
|
# Run the control and exit early if the experiment is not enabled.
|
66
|
-
control_obs = Observation.new("control", self)
|
67
|
-
control(...)
|
68
|
-
end
|
68
|
+
control_obs = Observation.new("control", self) { control }
|
69
69
|
raised(control_obs) if control_obs.raised?
|
70
|
-
return control_obs.value unless enabled?
|
70
|
+
return control_obs.value unless enabled?
|
71
71
|
|
72
|
-
candidate_obs = Observation.new("candidate", self)
|
73
|
-
candidate(...)
|
74
|
-
end
|
72
|
+
candidate_obs = Observation.new("candidate", self) { candidate }
|
75
73
|
raised(candidate_obs) if candidate_obs.raised?
|
76
74
|
|
77
75
|
# Compare and publish the results.
|
78
76
|
result = Result.new(self, control_obs, candidate_obs)
|
79
77
|
publish!(result)
|
80
78
|
|
79
|
+
# Reset the context for this run.
|
80
|
+
@context = {}
|
81
|
+
|
81
82
|
# Always return the control.
|
82
83
|
control_obs.value
|
83
84
|
end
|
data/lib/lab_coat/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lab_coat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Omkar Moghe
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|