julewire-core 1.0.1 → 1.1.1
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 +4 -4
- data/CHANGELOG.md +22 -0
- data/docs/configuration.md +14 -7
- data/docs/context-and-propagation.md +20 -0
- data/docs/contracts.md +23 -49
- data/docs/extensions-and-api.md +78 -82
- data/docs/health-schema.md +12 -2
- data/docs/internals.md +21 -20
- data/docs/outputs-and-lifecycle.md +10 -6
- data/docs/records-and-data-policy.md +36 -5
- data/lib/julewire/core/cli/doctor.rb +20 -16
- data/lib/julewire/core/cli/line_helpers.rb +23 -12
- data/lib/julewire/core/cli/log_formats/core_json_decoder.rb +3 -3
- data/lib/julewire/core/cli/log_formats.rb +9 -9
- data/lib/julewire/core/cli/tail.rb +19 -14
- data/lib/julewire/core/cli/transcode.rb +4 -5
- data/lib/julewire/core/cli.rb +1 -1
- data/lib/julewire/core/configuration.rb +1 -1
- data/lib/julewire/core/context_store.rb +51 -87
- data/lib/julewire/core/destinations/chaos_output.rb +2 -2
- data/lib/julewire/core/destinations/collection.rb +8 -16
- data/lib/julewire/core/destinations/definition.rb +1 -9
- data/lib/julewire/core/destinations/destination.rb +13 -63
- data/lib/julewire/core/destinations/processor_handling.rb +78 -0
- data/lib/julewire/core/destinations/registry.rb +1 -1
- data/lib/julewire/core/destinations/sink.rb +0 -1
- data/lib/julewire/core/destinations/synchronized_output.rb +14 -13
- data/lib/julewire/core/destinations/tail_sampling.rb +18 -27
- data/lib/julewire/core/destinations/write_step.rb +5 -5
- data/lib/julewire/core/destinations.rb +0 -7
- data/lib/julewire/core/diagnostics/callback_notifier.rb +4 -2
- data/lib/julewire/core/diagnostics/doctor.rb +16 -9
- data/lib/julewire/core/diagnostics/failure_snapshot.rb +6 -2
- data/lib/julewire/core/diagnostics/health.rb +41 -57
- data/lib/julewire/core/diagnostics/integration_health_store.rb +11 -24
- data/lib/julewire/core/diagnostics/internal_records.rb +8 -12
- data/lib/julewire/core/diagnostics/invalid_severity_reporter.rb +16 -55
- data/lib/julewire/core/diagnostics/meta_observer.rb +37 -44
- data/lib/julewire/core/diagnostics/process_integration_health.rb +0 -5
- data/lib/julewire/core/diagnostics/tail/renderer.rb +1 -1
- data/lib/julewire/core/diagnostics/tail.rb +18 -22
- data/lib/julewire/core/execution/boundary.rb +2 -8
- data/lib/julewire/core/execution/handle.rb +12 -17
- data/lib/julewire/core/execution/lineage.rb +16 -56
- data/lib/julewire/core/execution/measurement_handle.rb +6 -10
- data/lib/julewire/core/execution/scope.rb +15 -20
- data/lib/julewire/core/execution/scope_fields.rb +3 -12
- data/lib/julewire/core/execution/scope_identity.rb +1 -9
- data/lib/julewire/core/execution/scope_snapshot.rb +18 -39
- data/lib/julewire/core/execution/summary_state.rb +16 -19
- data/lib/julewire/core/execution/view.rb +8 -17
- data/lib/julewire/core/facade_methods.rb +67 -65
- data/lib/julewire/core/fields/attribute_keys.rb +0 -2
- data/lib/julewire/core/fields/bags.rb +23 -27
- data/lib/julewire/core/fields/field_set.rb +29 -19
- data/lib/julewire/core/fields/field_stack.rb +68 -134
- data/lib/julewire/core/fields/internal/deletion.rb +6 -9
- data/lib/julewire/core/fields/internal.rb +19 -38
- data/lib/julewire/core/fields/lookup.rb +9 -13
- data/lib/julewire/core/fields/section_proxy.rb +1 -9
- data/lib/julewire/core/fields/stack_set.rb +7 -12
- data/lib/julewire/core/fields/static_labels.rb +1 -1
- data/lib/julewire/core/integration/configurable.rb +4 -3
- data/lib/julewire/core/integration/destination_health.rb +17 -7
- data/lib/julewire/core/integration/event_subscriber.rb +1 -1
- data/lib/julewire/core/integration/facade.rb +12 -15
- data/lib/julewire/core/integration/fork_hooks.rb +12 -36
- data/lib/julewire/core/integration/health.rb +0 -3
- data/lib/julewire/core/integration/ivar_state.rb +0 -5
- data/lib/julewire/core/integration/protocol.rb +20 -0
- data/lib/julewire/core/integration/settings.rb +4 -4
- data/lib/julewire/core/integration/subscriber_install.rb +2 -2
- data/lib/julewire/core/integration/subscription.rb +3 -2
- data/lib/julewire/core/integration/values.rb +0 -17
- data/lib/julewire/core/local_storage.rb +3 -19
- data/lib/julewire/core/processing/invalid_result_failure.rb +23 -0
- data/lib/julewire/core/processing/level_threshold.rb +7 -14
- data/lib/julewire/core/processing/match.rb +6 -4
- data/lib/julewire/core/processing/pipeline.rb +46 -40
- data/lib/julewire/core/processing/processor_chain.rb +22 -11
- data/lib/julewire/core/processing/processor_registry.rb +3 -4
- data/lib/julewire/core/processing/record_field_transform.rb +0 -4
- data/lib/julewire/core/processing/sampling.rb +1 -3
- data/lib/julewire/core/processing.rb +2 -2
- data/lib/julewire/core/propagation/carrier.rb +14 -14
- data/lib/julewire/core/propagation.rb +15 -2
- data/lib/julewire/core/records/build_input.rb +75 -0
- data/lib/julewire/core/records/console_formatter.rb +6 -6
- data/lib/julewire/core/records/deconstruct.rb +1 -1
- data/lib/julewire/core/records/display_message.rb +2 -4
- data/lib/julewire/core/records/draft.rb +125 -262
- data/lib/julewire/core/records/lazy_emit_input.rb +2 -12
- data/lib/julewire/core/records/metadata.rb +4 -3
- data/lib/julewire/core/records/public_projection.rb +2 -2
- data/lib/julewire/core/records/raw_input.rb +1 -1
- data/lib/julewire/core/records/record.rb +19 -37
- data/lib/julewire/core/records/severity.rb +7 -15
- data/lib/julewire/core/runtime.rb +67 -71
- data/lib/julewire/core/runtime_registry.rb +20 -15
- data/lib/julewire/core/runtime_state.rb +5 -3
- data/lib/julewire/core/scheduling/shared_scheduler.rb +28 -22
- data/lib/julewire/core/serialization/backtrace_limiter.rb +13 -9
- data/lib/julewire/core/serialization/bounded_transform.rb +2 -12
- data/lib/julewire/core/serialization/bounded_traversal.rb +49 -66
- data/lib/julewire/core/serialization/deep_compact_empty.rb +9 -11
- data/lib/julewire/core/serialization/deep_freeze.rb +45 -6
- data/lib/julewire/core/serialization/encoding_sanitizer.rb +2 -3
- data/lib/julewire/core/serialization/exception_shape.rb +7 -6
- data/lib/julewire/core/serialization/json_encoder.rb +10 -13
- data/lib/julewire/core/serialization/serializer.rb +23 -50
- data/lib/julewire/core/serialization/serializer_pool.rb +9 -0
- data/lib/julewire/core/serialization/text_encoder.rb +5 -5
- data/lib/julewire/core/serialization/truncation_metadata.rb +63 -48
- data/lib/julewire/core/serialization/value_copy.rb +60 -227
- data/lib/julewire/core/serialization/value_traversal.rb +10 -127
- data/lib/julewire/core/testing.rb +6 -56
- data/lib/julewire/core/validation.rb +2 -3
- data/lib/julewire/core/version.rb +1 -1
- data/lib/julewire/core.rb +2 -7
- metadata +6 -19
- data/lib/julewire/core/scheduling/deadline_scheduler.rb +0 -207
- data/lib/julewire/core/testing/chaos/catalog.rb +0 -72
- data/lib/julewire/core/testing/chaos/core_runtime.rb +0 -120
- data/lib/julewire/core/testing/chaos/destination.rb +0 -55
- data/lib/julewire/core/testing/chaos/emitter.rb +0 -20
- data/lib/julewire/core/testing/chaos/raising_output.rb +0 -42
- data/lib/julewire/core/testing/chaos.rb +0 -80
- data/lib/julewire/core/testing/contracts/component.rb +0 -162
- data/lib/julewire/core/testing/contracts/deadline_scheduler.rb +0 -59
- data/lib/julewire/core/testing/contracts/integration.rb +0 -166
- data/lib/julewire/core/testing/contracts/integration_fields.rb +0 -36
- data/lib/julewire/core/testing/contracts/record_draft.rb +0 -37
- data/lib/julewire/core/testing/contracts/runtime.rb +0 -178
- data/lib/julewire/core/testing/contracts/wire.rb +0 -60
- data/lib/julewire/core/testing/contracts.rb +0 -24
- data/lib/julewire/core/testing/coverage.rb +0 -58
- data/lib/julewire/core/testing/test_reports.rb +0 -78
|
@@ -4,14 +4,11 @@ module Julewire
|
|
|
4
4
|
module Core
|
|
5
5
|
module Execution
|
|
6
6
|
class Scope
|
|
7
|
-
EMPTY_HASH = {}.freeze
|
|
8
|
-
private_constant :EMPTY_HASH
|
|
9
|
-
|
|
10
7
|
attr_reader :finished_at
|
|
11
8
|
|
|
12
|
-
def initialize(type:, id: nil, execution:
|
|
13
|
-
summary_severity: nil, summary_source: nil, attributes:
|
|
14
|
-
context:
|
|
9
|
+
def initialize(type:, id: nil, execution: nil, execution_owned: false, summary_event: nil, # rubocop:disable Metrics/ParameterLists
|
|
10
|
+
summary_severity: nil, summary_source: nil, attributes: nil, carry: nil,
|
|
11
|
+
context: nil, labels: nil, neutral: nil, parent: nil, started_at: nil)
|
|
15
12
|
@identity = ScopeIdentity.new(
|
|
16
13
|
type: type,
|
|
17
14
|
id: id,
|
|
@@ -37,7 +34,7 @@ module Julewire
|
|
|
37
34
|
def depth = @identity.depth
|
|
38
35
|
|
|
39
36
|
def execution_hash
|
|
40
|
-
Fields::FieldSet.
|
|
37
|
+
Fields::FieldSet.deep_dup_owned(frozen_execution_hash)
|
|
41
38
|
end
|
|
42
39
|
|
|
43
40
|
def frozen_execution_hash
|
|
@@ -45,7 +42,7 @@ module Julewire
|
|
|
45
42
|
end
|
|
46
43
|
|
|
47
44
|
def inheritable_execution_hash
|
|
48
|
-
Fields::FieldSet.
|
|
45
|
+
Fields::FieldSet.deep_dup_owned(@execution)
|
|
49
46
|
end
|
|
50
47
|
|
|
51
48
|
def context_hash = @fields.context_hash
|
|
@@ -96,7 +93,7 @@ module Julewire
|
|
|
96
93
|
end
|
|
97
94
|
end
|
|
98
95
|
|
|
99
|
-
def add_field(section, fields, owned:
|
|
96
|
+
def add_field(section, fields, owned:)
|
|
100
97
|
@fields.add(section, fields, owned: owned)
|
|
101
98
|
end
|
|
102
99
|
|
|
@@ -105,23 +102,22 @@ module Julewire
|
|
|
105
102
|
@fields.delete(:carry, path)
|
|
106
103
|
end
|
|
107
104
|
|
|
108
|
-
def with_field(section, fields, owned: false, &)
|
|
109
|
-
@fields.with(section, fields, owned: owned, &)
|
|
105
|
+
def with_field(section, fields, owned: false, **keyword_fields, &)
|
|
106
|
+
@fields.with(section, fields, owned: owned, **keyword_fields, &)
|
|
110
107
|
end
|
|
111
108
|
|
|
112
109
|
def with_context(fields = nil, owned: false, **keyword_fields, &)
|
|
113
|
-
|
|
110
|
+
with_field(:context, fields, owned: owned, **keyword_fields, &)
|
|
114
111
|
end
|
|
115
112
|
|
|
116
113
|
def with_carry(fields = nil, owned: false, **keyword_fields, &)
|
|
117
|
-
|
|
114
|
+
with_field(:carry, fields, owned: owned, **keyword_fields, &)
|
|
118
115
|
end
|
|
119
116
|
|
|
120
117
|
def without_carry(path, &)
|
|
121
|
-
|
|
122
|
-
raise ArgumentError, "carry path is required" if normalized_path.empty?
|
|
118
|
+
raise ArgumentError, "carry path is required" if Fields::Internal.normalize_path(path).empty?
|
|
123
119
|
|
|
124
|
-
@fields.without(:carry,
|
|
120
|
+
@fields.without(:carry, path, &)
|
|
125
121
|
end
|
|
126
122
|
|
|
127
123
|
def add_summary(fields, owned: false)
|
|
@@ -149,12 +145,12 @@ module Julewire
|
|
|
149
145
|
end
|
|
150
146
|
|
|
151
147
|
def summary_record_input
|
|
152
|
-
@summary_state.record_input(**summary_record_fields(timestamp:
|
|
148
|
+
@summary_state.record_input(**summary_record_fields(timestamp: frozen_time(Time.now.utc)))
|
|
153
149
|
end
|
|
154
150
|
|
|
155
151
|
def owned_summary_record_input
|
|
156
152
|
@summary_state.owned_record_input(
|
|
157
|
-
**summary_record_fields(timestamp:
|
|
153
|
+
**summary_record_fields(timestamp: frozen_time(Time.now.utc))
|
|
158
154
|
)
|
|
159
155
|
end
|
|
160
156
|
|
|
@@ -186,7 +182,7 @@ module Julewire
|
|
|
186
182
|
|
|
187
183
|
def frozen_time(value) = @identity.frozen_time(value)
|
|
188
184
|
|
|
189
|
-
def initialize_state(context:, attributes:, labels:, carry
|
|
185
|
+
def initialize_state(context:, attributes:, labels:, carry:, neutral:)
|
|
190
186
|
@fields = ScopeFields.new(
|
|
191
187
|
context: context,
|
|
192
188
|
carry: carry,
|
|
@@ -194,7 +190,6 @@ module Julewire
|
|
|
194
190
|
labels: labels,
|
|
195
191
|
neutral: neutral
|
|
196
192
|
)
|
|
197
|
-
@finished_at = nil
|
|
198
193
|
end
|
|
199
194
|
|
|
200
195
|
def summary_state(event, severity, source)
|
|
@@ -4,9 +4,6 @@ module Julewire
|
|
|
4
4
|
module Core
|
|
5
5
|
module Execution
|
|
6
6
|
class ScopeFields
|
|
7
|
-
EMPTY_HASH = {}.freeze
|
|
8
|
-
private_constant :EMPTY_HASH
|
|
9
|
-
|
|
10
7
|
attr_reader :stacks
|
|
11
8
|
|
|
12
9
|
def initialize(context:, attributes:, labels:, carry:, neutral:)
|
|
@@ -36,18 +33,14 @@ module Julewire
|
|
|
36
33
|
end
|
|
37
34
|
|
|
38
35
|
def labels_hash
|
|
39
|
-
return {} if @labels.empty?
|
|
40
|
-
|
|
41
36
|
Fields::FieldSet.deep_dup(@labels)
|
|
42
37
|
end
|
|
43
38
|
|
|
44
39
|
def frozen_labels_hash
|
|
45
|
-
return EMPTY_HASH if @labels.empty?
|
|
46
|
-
|
|
47
40
|
@frozen_labels_hash ||= Fields::Internal.frozen_copy(@labels)
|
|
48
41
|
end
|
|
49
42
|
|
|
50
|
-
def add(section, fields, owned:
|
|
43
|
+
def add(section, fields, owned:)
|
|
51
44
|
@stacks.add(section, fields, owned: owned)
|
|
52
45
|
end
|
|
53
46
|
|
|
@@ -55,7 +48,7 @@ module Julewire
|
|
|
55
48
|
@stacks.delete(section, path)
|
|
56
49
|
end
|
|
57
50
|
|
|
58
|
-
def with(section, fields
|
|
51
|
+
def with(section, fields, owned:, **keyword_fields, &)
|
|
59
52
|
@stacks.with(section, fields, owned: owned, **keyword_fields, &)
|
|
60
53
|
end
|
|
61
54
|
|
|
@@ -66,9 +59,7 @@ module Julewire
|
|
|
66
59
|
private
|
|
67
60
|
|
|
68
61
|
def normalized_static_hash(value)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Fields::FieldSet.deep_symbolize_keys(value)
|
|
62
|
+
Fields::FieldSet.deep_symbolize_keys(value || {})
|
|
72
63
|
end
|
|
73
64
|
end
|
|
74
65
|
end
|
|
@@ -55,15 +55,7 @@ module Julewire
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def freeze_identity_value(value)
|
|
58
|
-
|
|
59
|
-
when String
|
|
60
|
-
copy = value.frozen? ? value : value.dup
|
|
61
|
-
copy.freeze
|
|
62
|
-
when Symbol, Numeric, true, false, nil
|
|
63
|
-
value
|
|
64
|
-
else
|
|
65
|
-
Serialization::ValueCopy.call(value, freeze_values: true)
|
|
66
|
-
end
|
|
58
|
+
Serialization::ValueCopy.call(value, freeze_values: true)
|
|
67
59
|
end
|
|
68
60
|
end
|
|
69
61
|
end
|
|
@@ -4,10 +4,8 @@ module Julewire
|
|
|
4
4
|
module Core
|
|
5
5
|
module Execution
|
|
6
6
|
class ScopeSnapshot
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def initialize(execution: {}, carry: {}, attributes: {}, labels: {}, neutral: {}, lineage: nil)
|
|
7
|
+
def initialize(execution: {}, carry: {}, attributes: {}, labels: {}, neutral: {}, lineage: nil, owned: false)
|
|
8
|
+
@owned = owned
|
|
11
9
|
@execution = normalized_hash(execution)
|
|
12
10
|
@carry = normalized_hash(carry)
|
|
13
11
|
@attributes = normalized_hash(attributes)
|
|
@@ -17,11 +15,11 @@ module Julewire
|
|
|
17
15
|
end
|
|
18
16
|
|
|
19
17
|
def execution_hash
|
|
20
|
-
Fields::FieldSet.
|
|
18
|
+
Fields::FieldSet.deep_dup_owned(frozen_execution_hash)
|
|
21
19
|
end
|
|
22
20
|
|
|
23
21
|
def frozen_execution_hash
|
|
24
|
-
@frozen_execution_hash ||= Fields::Internal.
|
|
22
|
+
@frozen_execution_hash ||= Fields::Internal.frozen_owned_copy(@execution)
|
|
25
23
|
end
|
|
26
24
|
|
|
27
25
|
attr_reader :lineage
|
|
@@ -30,61 +28,42 @@ module Julewire
|
|
|
30
28
|
|
|
31
29
|
def type = @execution[:type]
|
|
32
30
|
|
|
33
|
-
def started_at
|
|
31
|
+
def started_at; end
|
|
34
32
|
|
|
35
|
-
def finished_at
|
|
33
|
+
def finished_at; end
|
|
36
34
|
|
|
37
|
-
def parent
|
|
35
|
+
def parent; end
|
|
38
36
|
|
|
39
37
|
def context_hash = {}
|
|
40
38
|
|
|
41
|
-
def carry_hash
|
|
42
|
-
return {} if @carry.empty?
|
|
43
|
-
|
|
44
|
-
Fields::FieldSet.deep_dup(@carry)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def attributes_hash
|
|
48
|
-
return {} if @attributes.empty?
|
|
39
|
+
def carry_hash = Fields::FieldSet.deep_dup_owned(@carry)
|
|
49
40
|
|
|
50
|
-
|
|
51
|
-
end
|
|
41
|
+
def attributes_hash = Fields::FieldSet.deep_dup_owned(@attributes)
|
|
52
42
|
|
|
53
|
-
def neutral_hash
|
|
54
|
-
return {} if @neutral.empty?
|
|
43
|
+
def neutral_hash = Fields::FieldSet.deep_dup_owned(@neutral)
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def labels_hash
|
|
60
|
-
return {} if @labels.empty?
|
|
61
|
-
|
|
62
|
-
Fields::FieldSet.deep_dup(@labels)
|
|
63
|
-
end
|
|
45
|
+
def labels_hash = Fields::FieldSet.deep_dup_owned(@labels)
|
|
64
46
|
|
|
65
47
|
def summary_hash = {}
|
|
66
48
|
|
|
67
49
|
def metrics_hash = {}
|
|
68
50
|
|
|
69
|
-
def frozen_labels_hash
|
|
70
|
-
return EMPTY_HASH if @labels.empty?
|
|
71
|
-
|
|
72
|
-
@frozen_labels_hash ||= Fields::Internal.frozen_copy(@labels)
|
|
73
|
-
end
|
|
51
|
+
def frozen_labels_hash = (@frozen_labels_hash ||= Fields::Internal.frozen_owned_copy(@labels))
|
|
74
52
|
|
|
75
53
|
def execution_reference_for_child
|
|
76
54
|
reference = {}
|
|
77
|
-
reference[:type] = @execution
|
|
78
|
-
reference[:id] = @execution
|
|
79
|
-
|
|
55
|
+
reference[:type] = @execution.fetch(:type) if @execution.key?(:type)
|
|
56
|
+
reference[:id] = @execution.fetch(:id) if @execution.key?(:id)
|
|
57
|
+
Fields::Internal.frozen_copy(reference) unless reference.empty?
|
|
80
58
|
end
|
|
81
59
|
|
|
82
60
|
private
|
|
83
61
|
|
|
84
62
|
def normalized_hash(value)
|
|
85
|
-
return
|
|
63
|
+
return Fields::FieldSet.deep_symbolize_keys(value) unless @owned
|
|
86
64
|
|
|
87
|
-
|
|
65
|
+
Serialization::DeepFreeze.validate_symbol_hash(value)
|
|
66
|
+
Fields::FieldSet.deep_dup_owned(value)
|
|
88
67
|
end
|
|
89
68
|
end
|
|
90
69
|
end
|
|
@@ -16,31 +16,29 @@ module Julewire
|
|
|
16
16
|
@attributes = {}
|
|
17
17
|
@metrics = {}
|
|
18
18
|
@errors = []
|
|
19
|
-
@error_severity = nil
|
|
20
|
-
@record_input = nil
|
|
21
19
|
end
|
|
22
20
|
|
|
23
21
|
def payload_hash
|
|
24
|
-
Fields::FieldSet.
|
|
22
|
+
Fields::FieldSet.deep_dup_owned(@payload)
|
|
25
23
|
end
|
|
26
24
|
|
|
27
25
|
def metrics_hash
|
|
28
|
-
Fields::FieldSet.
|
|
26
|
+
Fields::FieldSet.deep_dup_owned(@metrics)
|
|
29
27
|
end
|
|
30
28
|
|
|
31
|
-
def add(fields, owned:
|
|
29
|
+
def add(fields, owned:)
|
|
32
30
|
merge_fields!(@payload, fields, owned: owned)
|
|
33
31
|
end
|
|
34
32
|
|
|
35
|
-
def add_attributes(fields, owned:
|
|
33
|
+
def add_attributes(fields, owned:)
|
|
36
34
|
deep_merge_fields!(@attributes, fields, owned: owned)
|
|
37
35
|
end
|
|
38
36
|
|
|
39
|
-
def add_neutral(fields, owned:
|
|
37
|
+
def add_neutral(fields, owned:)
|
|
40
38
|
deep_merge_fields!(@neutral, fields, owned: owned)
|
|
41
39
|
end
|
|
42
40
|
|
|
43
|
-
def increment_attribute(path, by:
|
|
41
|
+
def increment_attribute(path, by:)
|
|
44
42
|
path = Fields::Internal.normalize_path(path)
|
|
45
43
|
raise ArgumentError, "attribute path is required" if path.empty?
|
|
46
44
|
|
|
@@ -48,7 +46,7 @@ module Julewire
|
|
|
48
46
|
key = path.last
|
|
49
47
|
value = Fields::FieldSet.value_for(container, key, default: MISSING)
|
|
50
48
|
existing = !value.equal?(MISSING)
|
|
51
|
-
container[
|
|
49
|
+
container[key] = incremented_value(value, by, existing: existing)
|
|
52
50
|
end
|
|
53
51
|
|
|
54
52
|
def increment(key, by: 1)
|
|
@@ -66,7 +64,7 @@ module Julewire
|
|
|
66
64
|
values << Fields::FieldSet.deep_dup(value)
|
|
67
65
|
end
|
|
68
66
|
|
|
69
|
-
def record_error(error, severity:
|
|
67
|
+
def record_error(error, severity:)
|
|
70
68
|
@errors << error
|
|
71
69
|
@error_severity = Records::Severity.normalize(severity) unless severity.nil?
|
|
72
70
|
end
|
|
@@ -90,7 +88,7 @@ module Julewire
|
|
|
90
88
|
end
|
|
91
89
|
|
|
92
90
|
def record_input(**fields)
|
|
93
|
-
Fields::FieldSet.
|
|
91
|
+
Fields::FieldSet.deep_dup_owned(owned_record_input(**fields))
|
|
94
92
|
end
|
|
95
93
|
|
|
96
94
|
def owned_record_input(**fields)
|
|
@@ -143,13 +141,13 @@ module Julewire
|
|
|
143
141
|
def attributes_hash(base_attributes)
|
|
144
142
|
return base_attributes if @attributes.empty?
|
|
145
143
|
|
|
146
|
-
Fields::Internal.
|
|
144
|
+
Fields::Internal.deep_merge_owned!(Fields::FieldSet.deep_dup_owned(base_attributes), @attributes)
|
|
147
145
|
end
|
|
148
146
|
|
|
149
147
|
def neutral_hash(base_neutral)
|
|
150
148
|
return base_neutral if @neutral.empty?
|
|
151
149
|
|
|
152
|
-
Fields::Internal.
|
|
150
|
+
Fields::Internal.deep_merge_owned!(Fields::FieldSet.deep_dup_owned(base_neutral), @neutral)
|
|
153
151
|
end
|
|
154
152
|
|
|
155
153
|
def array_value(value, existing:)
|
|
@@ -173,23 +171,22 @@ module Julewire
|
|
|
173
171
|
end
|
|
174
172
|
|
|
175
173
|
def measurement_base(key)
|
|
176
|
-
unless key.is_a?(String) || key.
|
|
174
|
+
unless key.is_a?(String) || key.instance_of?(Symbol)
|
|
177
175
|
raise ArgumentError, "measurement key must be a String or Symbol"
|
|
178
176
|
end
|
|
179
177
|
|
|
180
|
-
base = key
|
|
178
|
+
base = key
|
|
181
179
|
raise ArgumentError, "measurement key is required" if base.empty?
|
|
182
180
|
|
|
183
181
|
base
|
|
184
182
|
end
|
|
185
183
|
|
|
186
184
|
def attribute_container(path)
|
|
187
|
-
path[
|
|
188
|
-
|
|
189
|
-
child = container[normalized]
|
|
185
|
+
path[...-1].reduce(@attributes) do |container, key|
|
|
186
|
+
child = container[key]
|
|
190
187
|
unless child.is_a?(Hash)
|
|
191
188
|
child = {}
|
|
192
|
-
container[
|
|
189
|
+
container[key] = child
|
|
193
190
|
end
|
|
194
191
|
child
|
|
195
192
|
end
|
|
@@ -16,15 +16,6 @@ module Julewire
|
|
|
16
16
|
@finished_at = scope.finished_at
|
|
17
17
|
@parent_scope = scope.parent
|
|
18
18
|
@lineage = scope.lineage
|
|
19
|
-
@parent = nil
|
|
20
|
-
@execution_hash = nil
|
|
21
|
-
@context_hash = nil
|
|
22
|
-
@carry_hash = nil
|
|
23
|
-
@neutral_hash = nil
|
|
24
|
-
@attributes_hash = nil
|
|
25
|
-
@labels_hash = nil
|
|
26
|
-
@summary_hash = nil
|
|
27
|
-
@metrics_hash = nil
|
|
28
19
|
end
|
|
29
20
|
|
|
30
21
|
def parent
|
|
@@ -33,21 +24,21 @@ module Julewire
|
|
|
33
24
|
@parent ||= self.class.new(@parent_scope)
|
|
34
25
|
end
|
|
35
26
|
|
|
36
|
-
def execution_hash = Fields::FieldSet.
|
|
27
|
+
def execution_hash = Fields::FieldSet.deep_dup_owned(@execution_hash ||= @scope.frozen_execution_hash)
|
|
37
28
|
|
|
38
|
-
def context_hash = Fields::FieldSet.
|
|
29
|
+
def context_hash = Fields::FieldSet.deep_dup_owned(@context_hash ||= @scope.context_hash)
|
|
39
30
|
|
|
40
|
-
def carry_hash = Fields::FieldSet.
|
|
31
|
+
def carry_hash = Fields::FieldSet.deep_dup_owned(@carry_hash ||= @scope.carry_hash)
|
|
41
32
|
|
|
42
|
-
def neutral_hash = Fields::FieldSet.
|
|
33
|
+
def neutral_hash = Fields::FieldSet.deep_dup_owned(@neutral_hash ||= @scope.neutral_hash)
|
|
43
34
|
|
|
44
|
-
def attributes_hash = Fields::FieldSet.
|
|
35
|
+
def attributes_hash = Fields::FieldSet.deep_dup_owned(@attributes_hash ||= @scope.attributes_hash)
|
|
45
36
|
|
|
46
|
-
def labels_hash = Fields::FieldSet.
|
|
37
|
+
def labels_hash = Fields::FieldSet.deep_dup_owned(@labels_hash ||= @scope.frozen_labels_hash)
|
|
47
38
|
|
|
48
|
-
def summary_hash = Fields::FieldSet.
|
|
39
|
+
def summary_hash = Fields::FieldSet.deep_dup_owned(@summary_hash ||= @scope.summary_hash)
|
|
49
40
|
|
|
50
|
-
def metrics_hash = Fields::FieldSet.
|
|
41
|
+
def metrics_hash = Fields::FieldSet.deep_dup_owned(@metrics_hash ||= @scope.metrics_hash)
|
|
51
42
|
|
|
52
43
|
def finished? = !finished_at.nil?
|
|
53
44
|
end
|
|
@@ -2,54 +2,94 @@
|
|
|
2
2
|
|
|
3
3
|
module Julewire
|
|
4
4
|
module Core
|
|
5
|
+
module FacadePrivateMethods
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def punk_banner
|
|
9
|
+
"!!JULEWIRE PUNK!! chaos containment armed\n"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def punk_chaos_output(output, chaos)
|
|
13
|
+
options = chaos if chaos.is_a?(Hash)
|
|
14
|
+
Destinations::ChaosOutput.new(output, **options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def emit_with_severity(severity, record, fields, &)
|
|
18
|
+
if !block_given? && !record.is_a?(Hash)
|
|
19
|
+
# Scalar eager logs stay allocation-light; lazy inputs need the wrapper
|
|
20
|
+
# so block-built records can still receive the eager severity.
|
|
21
|
+
emit(eager_severity_input(severity, record, fields))
|
|
22
|
+
else
|
|
23
|
+
emit(Records::LazyEmitInput.with_severity(severity, Core.emit_input(record, fields)), &)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def eager_severity_input(severity, record, fields)
|
|
28
|
+
input = if record.equal?(UNSET)
|
|
29
|
+
fields
|
|
30
|
+
elsif fields.empty?
|
|
31
|
+
{ message: record.to_s }
|
|
32
|
+
else
|
|
33
|
+
Core.emit_input(record, fields)
|
|
34
|
+
end
|
|
35
|
+
input.delete("severity")
|
|
36
|
+
input[:severity] = severity
|
|
37
|
+
input
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def with_cleared_configure_guard
|
|
41
|
+
previous_guard = Fiber[Runtime::CONFIGURE_GUARD_KEY]
|
|
42
|
+
Fiber[Runtime::CONFIGURE_GUARD_KEY] = nil
|
|
43
|
+
yield
|
|
44
|
+
ensure
|
|
45
|
+
Fiber[Runtime::CONFIGURE_GUARD_KEY] = previous_guard
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
5
49
|
module FacadeMethods
|
|
50
|
+
include FacadePrivateMethods
|
|
51
|
+
|
|
6
52
|
def runtime(name = :default)
|
|
7
|
-
|
|
53
|
+
RuntimeRegistry.fetch(name)
|
|
8
54
|
end
|
|
9
55
|
|
|
10
56
|
def config = runtime.config
|
|
11
|
-
|
|
12
57
|
def configure(&) = runtime.configure(&)
|
|
13
|
-
|
|
14
58
|
def context = runtime.context
|
|
15
|
-
|
|
16
59
|
def attributes = runtime.attributes
|
|
17
|
-
|
|
18
60
|
def carry = runtime.carry
|
|
19
|
-
|
|
20
61
|
def current_execution = runtime.current_execution
|
|
21
|
-
|
|
22
62
|
def current_execution? = runtime.current_execution?
|
|
23
63
|
|
|
24
|
-
def emit(record =
|
|
64
|
+
def emit(record = UNSET, **fields, &)
|
|
25
65
|
runtime.emit(record, **fields, &)
|
|
26
66
|
end
|
|
27
67
|
|
|
28
|
-
def debug(record =
|
|
68
|
+
def debug(record = UNSET, **fields, &)
|
|
29
69
|
emit_with_severity(:debug, record, fields, &)
|
|
30
70
|
end
|
|
31
71
|
|
|
32
|
-
def info(record =
|
|
72
|
+
def info(record = UNSET, **fields, &)
|
|
33
73
|
emit_with_severity(:info, record, fields, &)
|
|
34
74
|
end
|
|
35
75
|
|
|
36
|
-
def warn(record =
|
|
76
|
+
def warn(record = UNSET, **fields, &)
|
|
37
77
|
emit_with_severity(:warn, record, fields, &)
|
|
38
78
|
end
|
|
39
79
|
|
|
40
|
-
def error(record =
|
|
80
|
+
def error(record = UNSET, **fields, &)
|
|
41
81
|
emit_with_severity(:error, record, fields, &)
|
|
42
82
|
end
|
|
43
83
|
|
|
44
|
-
def fatal(record =
|
|
84
|
+
def fatal(record = UNSET, **fields, &)
|
|
45
85
|
emit_with_severity(:fatal, record, fields, &)
|
|
46
86
|
end
|
|
47
87
|
|
|
48
|
-
def unknown(record =
|
|
88
|
+
def unknown(record = UNSET, **fields, &)
|
|
49
89
|
emit_with_severity(:unknown, record, fields, &)
|
|
50
90
|
end
|
|
51
91
|
|
|
52
|
-
def flush(timeout:
|
|
92
|
+
def flush(timeout: UNSET)
|
|
53
93
|
runtime.flush(timeout: timeout)
|
|
54
94
|
end
|
|
55
95
|
|
|
@@ -62,26 +102,26 @@ module Julewire
|
|
|
62
102
|
def measure_start(key) = summary.measure_start(key)
|
|
63
103
|
|
|
64
104
|
def doctor(name = :default)
|
|
65
|
-
|
|
105
|
+
Diagnostics::Doctor.call(runtime(name))
|
|
66
106
|
end
|
|
67
107
|
|
|
68
108
|
def tail(name = :default, **)
|
|
69
|
-
|
|
109
|
+
Diagnostics::Tail.attach!(runtime(name), **)
|
|
70
110
|
end
|
|
71
111
|
|
|
72
112
|
def observe_self!(name = :default, **)
|
|
73
|
-
|
|
113
|
+
Diagnostics::MetaObserver.attach!(name, **)
|
|
74
114
|
end
|
|
75
115
|
|
|
76
|
-
def dev!(name = :default, output: $stdout, color:
|
|
77
|
-
color = output.respond_to?(:tty?) ? output.tty? : true if color.equal?(
|
|
116
|
+
def dev!(name = :default, output: $stdout, color: UNSET, chaos: false, banner: chaos, tail: true)
|
|
117
|
+
color = output.respond_to?(:tty?) ? output.tty? : true if color.equal?(UNSET)
|
|
78
118
|
punk!(name, output: output, color: color, chaos: chaos, banner: banner)
|
|
79
119
|
return unless tail
|
|
80
120
|
|
|
81
121
|
tail_options = tail == true ? {} : tail
|
|
82
122
|
raise ArgumentError, "tail must be true, false, or an options Hash" unless tail_options.is_a?(Hash)
|
|
83
123
|
|
|
84
|
-
|
|
124
|
+
Tail.attach!(runtime(name), **tail_options)
|
|
85
125
|
end
|
|
86
126
|
|
|
87
127
|
def punk!(name = :default, output: $stdout, color: true, chaos: false, banner: chaos)
|
|
@@ -102,21 +142,19 @@ module Julewire
|
|
|
102
142
|
def fiber(**, &)
|
|
103
143
|
raise ArgumentError, "block required" unless block_given?
|
|
104
144
|
|
|
105
|
-
envelope =
|
|
145
|
+
envelope = Propagation.capture_local
|
|
106
146
|
Fiber.new(**) do |*args|
|
|
107
147
|
with_cleared_configure_guard do
|
|
108
|
-
|
|
148
|
+
Propagation.restore(envelope, owned: true) { yield(*args) }
|
|
109
149
|
end
|
|
110
150
|
end
|
|
111
151
|
end
|
|
112
152
|
|
|
113
153
|
def labels = runtime.labels
|
|
114
|
-
|
|
115
154
|
def after_fork! = runtime.after_fork!
|
|
155
|
+
def reset! = runtime.reset_facade!
|
|
116
156
|
|
|
117
|
-
def
|
|
118
|
-
|
|
119
|
-
def close(timeout: Core::UNSET)
|
|
157
|
+
def close(timeout: UNSET)
|
|
120
158
|
runtime.close(timeout: timeout)
|
|
121
159
|
end
|
|
122
160
|
|
|
@@ -129,10 +167,10 @@ module Julewire
|
|
|
129
167
|
def thread(*, &)
|
|
130
168
|
raise ArgumentError, "block required" unless block_given?
|
|
131
169
|
|
|
132
|
-
envelope =
|
|
170
|
+
envelope = Propagation.capture_local
|
|
133
171
|
Thread.new(*) do |*thread_args|
|
|
134
172
|
with_cleared_configure_guard do
|
|
135
|
-
|
|
173
|
+
Propagation.restore(envelope, owned: true) { yield(*thread_args) }
|
|
136
174
|
end
|
|
137
175
|
end
|
|
138
176
|
end
|
|
@@ -140,42 +178,6 @@ module Julewire
|
|
|
140
178
|
def with_execution(type:, **, &)
|
|
141
179
|
runtime.with_execution(type: type, **, &)
|
|
142
180
|
end
|
|
143
|
-
|
|
144
|
-
private
|
|
145
|
-
|
|
146
|
-
def punk_banner
|
|
147
|
-
"!!JULEWIRE PUNK!! chaos containment armed\n"
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def punk_chaos_output(output, chaos)
|
|
151
|
-
options = chaos.is_a?(Hash) ? chaos : {}
|
|
152
|
-
Core::Destinations::ChaosOutput.new(output, **options)
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def emit_with_severity(severity, record, fields, &)
|
|
156
|
-
if record.equal?(Core::UNSET)
|
|
157
|
-
fields.delete("severity")
|
|
158
|
-
fields[:severity] = severity
|
|
159
|
-
runtime.emit(fields, &)
|
|
160
|
-
elsif !block_given? && !record.is_a?(Hash)
|
|
161
|
-
# Scalar eager logs stay allocation-light; lazy inputs need the wrapper
|
|
162
|
-
# so block-built records can still receive the eager severity.
|
|
163
|
-
input = fields.empty? ? { message: record.to_s } : Core.emit_input(record, fields)
|
|
164
|
-
input.delete("severity")
|
|
165
|
-
input[:severity] = severity
|
|
166
|
-
runtime.emit(input)
|
|
167
|
-
else
|
|
168
|
-
runtime.emit(Core::Records::LazyEmitInput.with_severity(severity, Core.emit_input(record, fields)), &)
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def with_cleared_configure_guard
|
|
173
|
-
previous_guard = Fiber[Core::Runtime::CONFIGURE_GUARD_KEY]
|
|
174
|
-
Fiber[Core::Runtime::CONFIGURE_GUARD_KEY] = nil
|
|
175
|
-
yield
|
|
176
|
-
ensure
|
|
177
|
-
Fiber[Core::Runtime::CONFIGURE_GUARD_KEY] = previous_guard
|
|
178
|
-
end
|
|
179
181
|
end
|
|
180
182
|
end
|
|
181
183
|
end
|