temporalio 0.0.2 → 0.1.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 +4 -4
- data/README.md +25 -23
- data/bridge/Cargo.lock +168 -59
- data/bridge/Cargo.toml +4 -2
- data/bridge/sdk-core/README.md +19 -6
- data/bridge/sdk-core/client/src/lib.rs +215 -39
- data/bridge/sdk-core/client/src/metrics.rs +17 -8
- data/bridge/sdk-core/client/src/raw.rs +4 -4
- data/bridge/sdk-core/client/src/retry.rs +32 -20
- data/bridge/sdk-core/core/Cargo.toml +22 -9
- data/bridge/sdk-core/core/src/abstractions.rs +203 -14
- data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +76 -41
- data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
- data/bridge/sdk-core/core/src/core_tests/local_activities.rs +204 -83
- data/bridge/sdk-core/core/src/core_tests/queries.rs +3 -4
- data/bridge/sdk-core/core/src/core_tests/workers.rs +1 -3
- data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +397 -54
- data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
- data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
- data/bridge/sdk-core/core/src/lib.rs +16 -9
- data/bridge/sdk-core/core/src/telemetry/log_export.rs +1 -1
- data/bridge/sdk-core/core/src/telemetry/metrics.rs +69 -35
- data/bridge/sdk-core/core/src/telemetry/mod.rs +29 -13
- data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +17 -12
- data/bridge/sdk-core/core/src/test_help/mod.rs +62 -12
- data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
- data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +352 -122
- data/bridge/sdk-core/core/src/worker/activities.rs +233 -157
- data/bridge/sdk-core/core/src/worker/client/mocks.rs +22 -2
- data/bridge/sdk-core/core/src/worker/client.rs +18 -2
- data/bridge/sdk-core/core/src/worker/mod.rs +165 -58
- data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
- data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +856 -277
- data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +100 -43
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +7 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +87 -27
- data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +137 -62
- data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +25 -17
- data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +7 -6
- data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +103 -152
- data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +7 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
- data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +5 -16
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +201 -121
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +11 -14
- data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +30 -15
- data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1026 -376
- data/bridge/sdk-core/core/src/worker/workflow/mod.rs +460 -384
- data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
- data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +448 -718
- data/bridge/sdk-core/core-api/Cargo.toml +2 -1
- data/bridge/sdk-core/core-api/src/errors.rs +1 -34
- data/bridge/sdk-core/core-api/src/lib.rs +6 -2
- data/bridge/sdk-core/core-api/src/telemetry.rs +0 -6
- data/bridge/sdk-core/core-api/src/worker.rs +14 -1
- data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
- data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +5 -17
- data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +11 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +5 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +22 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +48 -19
- data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +3 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/{enums/v1/interaction_type.proto → protocol/v1/message.proto} +29 -11
- data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +111 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +59 -28
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +7 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
- data/bridge/sdk-core/sdk/Cargo.toml +3 -2
- data/bridge/sdk-core/sdk/src/lib.rs +87 -20
- data/bridge/sdk-core/sdk/src/workflow_future.rs +9 -8
- data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- data/bridge/sdk-core/sdk-core-protos/build.rs +36 -1
- data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +100 -87
- data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +5 -1
- data/bridge/sdk-core/sdk-core-protos/src/lib.rs +175 -57
- data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- data/bridge/sdk-core/test-utils/Cargo.toml +3 -1
- data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
- data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
- data/bridge/sdk-core/test-utils/src/lib.rs +82 -23
- data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
- data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
- data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -3
- data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
- data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
- data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +72 -191
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +12 -7
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
- data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +10 -11
- data/bridge/sdk-core/tests/main.rs +3 -13
- data/bridge/sdk-core/tests/runner.rs +75 -36
- data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
- data/bridge/src/connection.rs +41 -25
- data/bridge/src/lib.rs +269 -14
- data/bridge/src/runtime.rs +1 -1
- data/bridge/src/test_server.rs +153 -0
- data/bridge/src/worker.rs +89 -16
- data/lib/gen/temporal/api/command/v1/message_pb.rb +4 -18
- data/lib/gen/temporal/api/common/v1/message_pb.rb +4 -0
- data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +1 -3
- data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +3 -3
- data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +2 -0
- data/lib/gen/temporal/api/enums/v1/update_pb.rb +6 -4
- data/lib/gen/temporal/api/history/v1/message_pb.rb +27 -19
- data/lib/gen/temporal/api/namespace/v1/message_pb.rb +1 -0
- data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +3 -0
- data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
- data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
- data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
- data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
- data/lib/gen/temporal/api/update/v1/message_pb.rb +72 -0
- data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +26 -16
- data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
- data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
- data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +27 -21
- data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +28 -24
- data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
- data/lib/temporalio/activity/context.rb +13 -8
- data/lib/temporalio/activity/info.rb +1 -1
- data/lib/temporalio/bridge/connect_options.rb +15 -0
- data/lib/temporalio/bridge/retry_config.rb +24 -0
- data/lib/temporalio/bridge/tls_options.rb +19 -0
- data/lib/temporalio/client/implementation.rb +8 -8
- data/lib/temporalio/connection/retry_config.rb +44 -0
- data/lib/temporalio/connection/service.rb +20 -0
- data/lib/temporalio/connection/test_service.rb +92 -0
- data/lib/temporalio/connection/tls_options.rb +51 -0
- data/lib/temporalio/connection/workflow_service.rb +731 -0
- data/lib/temporalio/connection.rb +55 -720
- data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
- data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
- data/lib/temporalio/interceptor/chain.rb +5 -5
- data/lib/temporalio/interceptor/client.rb +8 -4
- data/lib/temporalio/interceptor.rb +22 -0
- data/lib/temporalio/retry_policy.rb +13 -3
- data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
- data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
- data/lib/temporalio/testing/workflow_environment.rb +112 -0
- data/lib/temporalio/testing.rb +175 -0
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/worker/activity_runner.rb +26 -4
- data/lib/temporalio/worker/activity_worker.rb +44 -18
- data/lib/temporalio/worker/sync_worker.rb +47 -11
- data/lib/temporalio/worker.rb +27 -21
- data/lib/temporalio/workflow/async.rb +46 -0
- data/lib/temporalio/workflow/future.rb +138 -0
- data/lib/temporalio/workflow/info.rb +76 -0
- data/temporalio.gemspec +4 -3
- metadata +67 -17
- data/bridge/sdk-core/Cargo.lock +0 -2606
- data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +0 -87
- data/lib/bridge.so +0 -0
- data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +0 -25
- data/lib/gen/temporal/api/interaction/v1/message_pb.rb +0 -49
- data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
|
@@ -23,6 +23,9 @@ use std::os::unix::fs::OpenOptionsExt;
|
|
|
23
23
|
use std::process::Stdio;
|
|
24
24
|
|
|
25
25
|
/// Configuration for Temporalite.
|
|
26
|
+
/// Will be removed eventually as its successor, Temporal CLI matures.
|
|
27
|
+
/// We don't care for the duplication between this struct and [TemporalDevServerConfig] and prefer that over another
|
|
28
|
+
/// abstraction since the existence of this struct is temporary.
|
|
26
29
|
#[derive(Debug, Clone, derive_builder::Builder)]
|
|
27
30
|
pub struct TemporaliteConfig {
|
|
28
31
|
/// Required path to executable or download info.
|
|
@@ -59,7 +62,10 @@ impl TemporaliteConfig {
|
|
|
59
62
|
/// Start a Temporalite server with configurable stdout destination.
|
|
60
63
|
pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
|
|
61
64
|
// Get exe path
|
|
62
|
-
let exe_path = self
|
|
65
|
+
let exe_path = self
|
|
66
|
+
.exe
|
|
67
|
+
.get_or_download("temporalite", "temporalite")
|
|
68
|
+
.await?;
|
|
63
69
|
|
|
64
70
|
// Get free port if not already given
|
|
65
71
|
let port = self.port.unwrap_or_else(|| get_free_port(&self.ip));
|
|
@@ -77,6 +83,8 @@ impl TemporaliteConfig {
|
|
|
77
83
|
self.log.0.clone(),
|
|
78
84
|
"--log-level".to_owned(),
|
|
79
85
|
self.log.1.clone(),
|
|
86
|
+
"--dynamic-config-value".to_owned(),
|
|
87
|
+
"frontend.enableServerVersionCheck=false".to_owned(),
|
|
80
88
|
];
|
|
81
89
|
if let Some(db_filename) = &self.db_filename {
|
|
82
90
|
args.push("--filename".to_owned());
|
|
@@ -101,6 +109,86 @@ impl TemporaliteConfig {
|
|
|
101
109
|
}
|
|
102
110
|
}
|
|
103
111
|
|
|
112
|
+
/// Configuration for Temporal CLI dev server.
|
|
113
|
+
#[derive(Debug, Clone, derive_builder::Builder)]
|
|
114
|
+
pub struct TemporalDevServerConfig {
|
|
115
|
+
/// Required path to executable or download info.
|
|
116
|
+
pub exe: EphemeralExe,
|
|
117
|
+
/// Namespace to use.
|
|
118
|
+
#[builder(default = "\"default\".to_owned()")]
|
|
119
|
+
pub namespace: String,
|
|
120
|
+
/// IP to bind to.
|
|
121
|
+
#[builder(default = "\"127.0.0.1\".to_owned()")]
|
|
122
|
+
pub ip: String,
|
|
123
|
+
/// Port to use or obtains a free one if none given.
|
|
124
|
+
#[builder(default)]
|
|
125
|
+
pub port: Option<u16>,
|
|
126
|
+
/// Sqlite DB filename if persisting or non-persistent if none.
|
|
127
|
+
#[builder(default)]
|
|
128
|
+
pub db_filename: Option<String>,
|
|
129
|
+
/// Whether to enable the UI.
|
|
130
|
+
#[builder(default)]
|
|
131
|
+
pub ui: bool,
|
|
132
|
+
/// Log format and level
|
|
133
|
+
#[builder(default = "(\"pretty\".to_owned(), \"warn\".to_owned())")]
|
|
134
|
+
pub log: (String, String),
|
|
135
|
+
/// Additional arguments to Temporalite.
|
|
136
|
+
#[builder(default)]
|
|
137
|
+
pub extra_args: Vec<String>,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
impl TemporalDevServerConfig {
|
|
141
|
+
/// Start a Temporal CLI dev server.
|
|
142
|
+
pub async fn start_server(&self) -> anyhow::Result<EphemeralServer> {
|
|
143
|
+
self.start_server_with_output(Stdio::inherit()).await
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/// Start a Temporal CLI dev server with configurable stdout destination.
|
|
147
|
+
pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
|
|
148
|
+
// Get exe path
|
|
149
|
+
let exe_path = self.exe.get_or_download("cli", "temporal").await?;
|
|
150
|
+
|
|
151
|
+
// Get free port if not already given
|
|
152
|
+
let port = self.port.unwrap_or_else(|| get_free_port(&self.ip));
|
|
153
|
+
|
|
154
|
+
// Build arg set
|
|
155
|
+
let mut args = vec![
|
|
156
|
+
"server".to_owned(),
|
|
157
|
+
"start-dev".to_owned(),
|
|
158
|
+
"--port".to_owned(),
|
|
159
|
+
port.to_string(),
|
|
160
|
+
"--namespace".to_owned(),
|
|
161
|
+
self.namespace.clone(),
|
|
162
|
+
"--ip".to_owned(),
|
|
163
|
+
self.ip.clone(),
|
|
164
|
+
"--log-format".to_owned(),
|
|
165
|
+
self.log.0.clone(),
|
|
166
|
+
"--log-level".to_owned(),
|
|
167
|
+
self.log.1.clone(),
|
|
168
|
+
"--dynamic-config-value".to_owned(),
|
|
169
|
+
"frontend.enableServerVersionCheck=false".to_owned(),
|
|
170
|
+
];
|
|
171
|
+
if let Some(db_filename) = &self.db_filename {
|
|
172
|
+
args.push("--filename".to_owned());
|
|
173
|
+
args.push(db_filename.clone());
|
|
174
|
+
}
|
|
175
|
+
if !self.ui {
|
|
176
|
+
args.push("--headless".to_owned());
|
|
177
|
+
}
|
|
178
|
+
args.extend(self.extra_args.clone());
|
|
179
|
+
|
|
180
|
+
// Start
|
|
181
|
+
EphemeralServer::start(EphemeralServerConfig {
|
|
182
|
+
exe_path,
|
|
183
|
+
port,
|
|
184
|
+
args,
|
|
185
|
+
has_test_service: false,
|
|
186
|
+
output,
|
|
187
|
+
})
|
|
188
|
+
.await
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
104
192
|
/// Configuration for the test server.
|
|
105
193
|
#[derive(Debug, Clone, derive_builder::Builder)]
|
|
106
194
|
pub struct TestServerConfig {
|
|
@@ -123,7 +211,10 @@ impl TestServerConfig {
|
|
|
123
211
|
/// Start a test server with configurable stdout.
|
|
124
212
|
pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
|
|
125
213
|
// Get exe path
|
|
126
|
-
let exe_path = self
|
|
214
|
+
let exe_path = self
|
|
215
|
+
.exe
|
|
216
|
+
.get_or_download("temporal-test-server", "temporal-test-server")
|
|
217
|
+
.await?;
|
|
127
218
|
|
|
128
219
|
// Get free port if not already given
|
|
129
220
|
let port = self.port.unwrap_or_else(|| get_free_port("0.0.0.0"));
|
|
@@ -172,7 +263,7 @@ impl EphemeralServer {
|
|
|
172
263
|
.stdout(config.output)
|
|
173
264
|
.spawn()?;
|
|
174
265
|
let target = format!("127.0.0.1:{}", config.port);
|
|
175
|
-
let target_url = format!("http://{}"
|
|
266
|
+
let target_url = format!("http://{target}");
|
|
176
267
|
let success = Ok(EphemeralServer {
|
|
177
268
|
target,
|
|
178
269
|
has_test_service: config.has_test_service,
|
|
@@ -262,7 +353,7 @@ pub enum EphemeralExe {
|
|
|
262
353
|
#[derive(Debug, Clone)]
|
|
263
354
|
pub enum EphemeralExeVersion {
|
|
264
355
|
/// Use a default version for the given SDK name and version.
|
|
265
|
-
|
|
356
|
+
SDKDefault {
|
|
266
357
|
/// Name of the SDK to get the default for.
|
|
267
358
|
sdk_name: String,
|
|
268
359
|
/// Version of the SDK to get the default for.
|
|
@@ -280,7 +371,11 @@ struct DownloadInfo {
|
|
|
280
371
|
}
|
|
281
372
|
|
|
282
373
|
impl EphemeralExe {
|
|
283
|
-
async fn get_or_download(
|
|
374
|
+
async fn get_or_download(
|
|
375
|
+
&self,
|
|
376
|
+
artifact_name: &str,
|
|
377
|
+
downloaded_name_prefix: &str,
|
|
378
|
+
) -> anyhow::Result<PathBuf> {
|
|
284
379
|
match self {
|
|
285
380
|
EphemeralExe::ExistingPath(exe_path) => {
|
|
286
381
|
let path = PathBuf::from(exe_path);
|
|
@@ -301,12 +396,12 @@ impl EphemeralExe {
|
|
|
301
396
|
};
|
|
302
397
|
// Create dest file based on SDK name/version or fixed version
|
|
303
398
|
let dest = dest_dir.join(match version {
|
|
304
|
-
EphemeralExeVersion::
|
|
399
|
+
EphemeralExeVersion::SDKDefault {
|
|
305
400
|
sdk_name,
|
|
306
401
|
sdk_version,
|
|
307
|
-
} => format!("{}-{}-{}{}"
|
|
402
|
+
} => format!("{downloaded_name_prefix}-{sdk_name}-{sdk_version}{out_ext}"),
|
|
308
403
|
EphemeralExeVersion::Fixed(version) => {
|
|
309
|
-
format!("{}-{}{}"
|
|
404
|
+
format!("{downloaded_name_prefix}-{version}{out_ext}")
|
|
310
405
|
}
|
|
311
406
|
});
|
|
312
407
|
debug!(
|
|
@@ -327,7 +422,7 @@ impl EphemeralExe {
|
|
|
327
422
|
};
|
|
328
423
|
let mut get_info_params = vec![("arch", arch), ("platform", platform)];
|
|
329
424
|
let version_name = match version {
|
|
330
|
-
EphemeralExeVersion::
|
|
425
|
+
EphemeralExeVersion::SDKDefault {
|
|
331
426
|
sdk_name,
|
|
332
427
|
sdk_version,
|
|
333
428
|
} => {
|
|
@@ -340,8 +435,7 @@ impl EphemeralExe {
|
|
|
340
435
|
let client = reqwest::Client::new();
|
|
341
436
|
let info: DownloadInfo = client
|
|
342
437
|
.get(format!(
|
|
343
|
-
"https://temporal.download/{}/{}"
|
|
344
|
-
artifact_name, version_name
|
|
438
|
+
"https://temporal.download/{artifact_name}/{version_name}"
|
|
345
439
|
))
|
|
346
440
|
.query(&get_info_params)
|
|
347
441
|
.send()
|
|
@@ -371,7 +465,7 @@ impl EphemeralExe {
|
|
|
371
465
|
fn get_free_port(bind_ip: &str) -> u16 {
|
|
372
466
|
// Can just ask OS to give us a port then close socket. OS's don't give that
|
|
373
467
|
// port back to anyone else anytime soon.
|
|
374
|
-
std::net::TcpListener::bind(format!("{}:0"
|
|
468
|
+
std::net::TcpListener::bind(format!("{bind_ip}:0"))
|
|
375
469
|
.unwrap()
|
|
376
470
|
.local_addr()
|
|
377
471
|
.unwrap()
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
//! Utilities for and tracking of internal versions which alter history in incompatible ways
|
|
2
|
+
//! so that we can use older code paths for workflows executed on older core versions.
|
|
3
|
+
|
|
4
|
+
use std::collections::{BTreeSet, HashSet};
|
|
5
|
+
use temporal_sdk_core_protos::temporal::api::{
|
|
6
|
+
history::v1::WorkflowTaskCompletedEventAttributes, sdk::v1::WorkflowTaskCompletedMetadata,
|
|
7
|
+
workflowservice::v1::get_system_info_response,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/// This enumeration contains internal flags that may result in incompatible history changes with
|
|
11
|
+
/// older workflows, or other breaking changes.
|
|
12
|
+
///
|
|
13
|
+
/// When a flag has existed long enough the version it was introduced in is no longer supported, it
|
|
14
|
+
/// may be removed from the enum. *Importantly*, all variants must be given explicit values, such
|
|
15
|
+
/// that removing older variants does not create any change in existing values. Removed flag
|
|
16
|
+
/// variants must be reserved forever (a-la protobuf), and should be called out in a comment.
|
|
17
|
+
#[repr(u32)]
|
|
18
|
+
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone, Debug)]
|
|
19
|
+
pub(crate) enum CoreInternalFlags {
|
|
20
|
+
/// In this flag, additional checks were added to a number of state machines to ensure that
|
|
21
|
+
/// the ID and type of activities, local activities, and child workflows match during replay.
|
|
22
|
+
IdAndTypeDeterminismChecks = 1,
|
|
23
|
+
/// We received a value higher than this code can understand.
|
|
24
|
+
TooHigh = u32::MAX,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
28
|
+
pub(crate) struct InternalFlags {
|
|
29
|
+
enabled: bool,
|
|
30
|
+
core: BTreeSet<CoreInternalFlags>,
|
|
31
|
+
lang: BTreeSet<u32>,
|
|
32
|
+
core_since_last_complete: HashSet<CoreInternalFlags>,
|
|
33
|
+
lang_since_last_complete: HashSet<u32>,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
impl InternalFlags {
|
|
37
|
+
pub fn new(server_capabilities: &get_system_info_response::Capabilities) -> Self {
|
|
38
|
+
Self {
|
|
39
|
+
enabled: server_capabilities.sdk_metadata,
|
|
40
|
+
core: Default::default(),
|
|
41
|
+
lang: Default::default(),
|
|
42
|
+
core_since_last_complete: Default::default(),
|
|
43
|
+
lang_since_last_complete: Default::default(),
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
pub fn add_from_complete(&mut self, e: &WorkflowTaskCompletedEventAttributes) {
|
|
48
|
+
if !self.enabled {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if let Some(metadata) = e.sdk_metadata.as_ref() {
|
|
53
|
+
self.core.extend(
|
|
54
|
+
metadata
|
|
55
|
+
.core_used_flags
|
|
56
|
+
.iter()
|
|
57
|
+
.map(|u| CoreInternalFlags::from_u32(*u)),
|
|
58
|
+
);
|
|
59
|
+
self.lang.extend(metadata.lang_used_flags.iter());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pub fn add_lang_used(&mut self, flags: impl IntoIterator<Item = u32>) {
|
|
64
|
+
if !self.enabled {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
self.lang_since_last_complete.extend(flags.into_iter());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/// Returns true if this flag may currently be used. If `should_record` is true, always returns
|
|
72
|
+
/// true and records the flag as being used, for taking later via
|
|
73
|
+
/// [Self::gather_for_wft_complete].
|
|
74
|
+
pub fn try_use(&mut self, core_patch: CoreInternalFlags, should_record: bool) -> bool {
|
|
75
|
+
if !self.enabled {
|
|
76
|
+
// If the server does not support the metadata field, we must assume
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if should_record {
|
|
81
|
+
self.core_since_last_complete.insert(core_patch);
|
|
82
|
+
true
|
|
83
|
+
} else {
|
|
84
|
+
self.core.contains(&core_patch)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// Wipes the recorded flags used during the current WFT and returns a partially filled
|
|
89
|
+
/// sdk metadata message that can be combined with any existing data before sending the WFT
|
|
90
|
+
/// complete
|
|
91
|
+
pub fn gather_for_wft_complete(&mut self) -> WorkflowTaskCompletedMetadata {
|
|
92
|
+
WorkflowTaskCompletedMetadata {
|
|
93
|
+
core_used_flags: self
|
|
94
|
+
.core_since_last_complete
|
|
95
|
+
.drain()
|
|
96
|
+
.map(|p| p as u32)
|
|
97
|
+
.collect(),
|
|
98
|
+
lang_used_flags: self.lang_since_last_complete.drain().collect(),
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
pub fn all_lang(&self) -> &BTreeSet<u32> {
|
|
103
|
+
&self.lang
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
impl CoreInternalFlags {
|
|
108
|
+
fn from_u32(v: u32) -> Self {
|
|
109
|
+
match v {
|
|
110
|
+
1 => Self::IdAndTypeDeterminismChecks,
|
|
111
|
+
_ => Self::TooHigh,
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#[cfg(test)]
|
|
117
|
+
mod tests {
|
|
118
|
+
use super::*;
|
|
119
|
+
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::get_system_info_response::Capabilities;
|
|
120
|
+
|
|
121
|
+
#[test]
|
|
122
|
+
fn disabled_in_capabilities_disables() {
|
|
123
|
+
let mut f = InternalFlags::new(&Capabilities::default());
|
|
124
|
+
f.add_lang_used([1]);
|
|
125
|
+
f.add_from_complete(&WorkflowTaskCompletedEventAttributes {
|
|
126
|
+
sdk_metadata: Some(WorkflowTaskCompletedMetadata {
|
|
127
|
+
core_used_flags: vec![1],
|
|
128
|
+
lang_used_flags: vec![],
|
|
129
|
+
}),
|
|
130
|
+
..Default::default()
|
|
131
|
+
});
|
|
132
|
+
let gathered = f.gather_for_wft_complete();
|
|
133
|
+
assert_matches!(gathered.core_used_flags.as_slice(), &[]);
|
|
134
|
+
assert_matches!(gathered.lang_used_flags.as_slice(), &[]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -13,6 +13,7 @@ extern crate core;
|
|
|
13
13
|
|
|
14
14
|
mod abstractions;
|
|
15
15
|
pub mod ephemeral_server;
|
|
16
|
+
mod internal_flags;
|
|
16
17
|
mod pollers;
|
|
17
18
|
mod protosext;
|
|
18
19
|
pub mod replay;
|
|
@@ -36,13 +37,16 @@ pub use temporal_sdk_core_api as api;
|
|
|
36
37
|
pub use temporal_sdk_core_protos as protos;
|
|
37
38
|
pub use temporal_sdk_core_protos::TaskToken;
|
|
38
39
|
pub use url::Url;
|
|
40
|
+
#[cfg(feature = "save_wf_inputs")]
|
|
41
|
+
pub use worker::replay_wf_state_inputs;
|
|
39
42
|
pub use worker::{Worker, WorkerConfig, WorkerConfigBuilder};
|
|
40
43
|
|
|
41
44
|
use crate::{
|
|
42
45
|
replay::{mock_client_from_histories, Historator, HistoryForReplay},
|
|
43
46
|
telemetry::{
|
|
44
|
-
metrics::MetricsContext,
|
|
45
|
-
|
|
47
|
+
metrics::{MetricsContext, TemporalMeter},
|
|
48
|
+
remove_trace_subscriber_for_current_thread, set_trace_subscriber_for_current_thread,
|
|
49
|
+
telemetry_init, TelemetryInstance,
|
|
46
50
|
},
|
|
47
51
|
worker::client::WorkerClientBag,
|
|
48
52
|
};
|
|
@@ -51,7 +55,7 @@ use std::sync::Arc;
|
|
|
51
55
|
use temporal_client::{ConfiguredClient, TemporalServiceClientWithMetrics};
|
|
52
56
|
use temporal_sdk_core_api::{
|
|
53
57
|
errors::{CompleteActivityError, PollActivityError, PollWfError},
|
|
54
|
-
telemetry::
|
|
58
|
+
telemetry::TelemetryOptions,
|
|
55
59
|
Worker as WorkerTrait,
|
|
56
60
|
};
|
|
57
61
|
use temporal_sdk_core_protos::coresdk::ActivityHeartbeat;
|
|
@@ -62,7 +66,7 @@ use temporal_sdk_core_protos::coresdk::ActivityHeartbeat;
|
|
|
62
66
|
/// After the worker is initialized, you should use [CoreRuntime::tokio_handle] to run the worker's
|
|
63
67
|
/// async functions.
|
|
64
68
|
///
|
|
65
|
-
/// Lang implementations may pass in a [
|
|
69
|
+
/// Lang implementations may pass in a [ConfiguredClient] directly (or a
|
|
66
70
|
/// [RetryClient] wrapping one, or a handful of other variants of the same idea). When they do so,
|
|
67
71
|
/// this function will always overwrite the client retry configuration, force the client to use the
|
|
68
72
|
/// namespace defined in the worker config, and set the client identity appropriately. IE: Use
|
|
@@ -97,9 +101,12 @@ where
|
|
|
97
101
|
worker_config.use_worker_versioning,
|
|
98
102
|
));
|
|
99
103
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
Ok(Worker::new(
|
|
105
|
+
worker_config,
|
|
106
|
+
sticky_q,
|
|
107
|
+
client_bag,
|
|
108
|
+
Some(&runtime.telemetry),
|
|
109
|
+
))
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
/// Create a worker for replaying a specific history. It will auto-shutdown as soon as the history
|
|
@@ -126,7 +133,7 @@ where
|
|
|
126
133
|
let post_activate = historator.get_post_activate_hook();
|
|
127
134
|
let shutdown_tok = historator.get_shutdown_setter();
|
|
128
135
|
let client = mock_client_from_histories(historator);
|
|
129
|
-
let mut worker = Worker::new(config, None, Arc::new(client),
|
|
136
|
+
let mut worker = Worker::new(config, None, Arc::new(client), None);
|
|
130
137
|
worker.set_post_activate_hook(post_activate);
|
|
131
138
|
shutdown_tok(worker.shutdown_token());
|
|
132
139
|
Ok(worker)
|
|
@@ -258,7 +265,7 @@ impl CoreRuntime {
|
|
|
258
265
|
}
|
|
259
266
|
|
|
260
267
|
/// Returns the metric meter used for recording metrics, if they were enabled.
|
|
261
|
-
pub fn metric_meter(&self) -> Option
|
|
268
|
+
pub fn metric_meter(&self) -> Option<TemporalMeter> {
|
|
262
269
|
self.telemetry.get_metric_meter()
|
|
263
270
|
}
|
|
264
271
|
|
|
@@ -139,7 +139,7 @@ impl<'a> tracing::field::Visit for JsonVisitor<'a> {
|
|
|
139
139
|
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
|
|
140
140
|
self.0.insert(
|
|
141
141
|
field.name().to_string(),
|
|
142
|
-
serde_json::json!(format!("{:?}"
|
|
142
|
+
serde_json::json!(format!("{value:?}")),
|
|
143
143
|
);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
@@ -10,8 +10,8 @@ use opentelemetry::{
|
|
|
10
10
|
},
|
|
11
11
|
Context, KeyValue,
|
|
12
12
|
};
|
|
13
|
-
use std::{sync::Arc, time::Duration};
|
|
14
|
-
use
|
|
13
|
+
use std::{ops::Deref, sync::Arc, time::Duration};
|
|
14
|
+
use temporal_client::ClientMetricProvider;
|
|
15
15
|
|
|
16
16
|
/// Used to track context associated with metrics, and record/update them
|
|
17
17
|
///
|
|
@@ -24,6 +24,46 @@ pub(crate) struct MetricsContext {
|
|
|
24
24
|
instruments: Arc<Instruments>,
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/// Wraps OTel's [Meter] to ensure we name our metrics properly, or any other temporal-specific
|
|
28
|
+
/// metrics customizations
|
|
29
|
+
#[derive(derive_more::Constructor)]
|
|
30
|
+
pub struct TemporalMeter<'a> {
|
|
31
|
+
inner: &'a Meter,
|
|
32
|
+
metrics_prefix: &'static str,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
impl<'a> TemporalMeter<'a> {
|
|
36
|
+
pub(crate) fn counter(&self, name: &'static str) -> Counter<u64> {
|
|
37
|
+
self.inner
|
|
38
|
+
.u64_counter(self.metrics_prefix.to_string() + name)
|
|
39
|
+
.init()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pub(crate) fn histogram(&self, name: &'static str) -> Histogram<u64> {
|
|
43
|
+
self.inner
|
|
44
|
+
.u64_histogram(self.metrics_prefix.to_string() + name)
|
|
45
|
+
.init()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
impl<'a> ClientMetricProvider for TemporalMeter<'a> {
|
|
50
|
+
fn counter(&self, name: &'static str) -> Counter<u64> {
|
|
51
|
+
self.counter(name)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fn histogram(&self, name: &'static str) -> Histogram<u64> {
|
|
55
|
+
self.histogram(name)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
impl<'a> Deref for TemporalMeter<'a> {
|
|
60
|
+
type Target = dyn ClientMetricProvider + 'a;
|
|
61
|
+
|
|
62
|
+
fn deref(&self) -> &Self::Target {
|
|
63
|
+
self as &Self::Target
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
27
67
|
struct Instruments {
|
|
28
68
|
wf_completed_counter: Counter<u64>,
|
|
29
69
|
wf_canceled_counter: Counter<u64>,
|
|
@@ -54,10 +94,10 @@ impl MetricsContext {
|
|
|
54
94
|
Self {
|
|
55
95
|
ctx: Default::default(),
|
|
56
96
|
kvs: Default::default(),
|
|
57
|
-
instruments: Arc::new(Instruments::new_explicit(
|
|
97
|
+
instruments: Arc::new(Instruments::new_explicit(TemporalMeter::new(
|
|
58
98
|
&NoopMeterProvider::new().meter("fakemeter"),
|
|
59
99
|
"fakemetrics",
|
|
60
|
-
)),
|
|
100
|
+
))),
|
|
61
101
|
}
|
|
62
102
|
}
|
|
63
103
|
|
|
@@ -257,42 +297,36 @@ impl Instruments {
|
|
|
257
297
|
meter
|
|
258
298
|
} else {
|
|
259
299
|
no_op_meter = NoopMeterProvider::default().meter("no_op");
|
|
260
|
-
&no_op_meter
|
|
300
|
+
TemporalMeter::new(&no_op_meter, "fakemetrics")
|
|
261
301
|
};
|
|
262
|
-
Self::new_explicit(meter
|
|
302
|
+
Self::new_explicit(meter)
|
|
263
303
|
}
|
|
264
304
|
|
|
265
|
-
fn new_explicit(meter:
|
|
266
|
-
let ctr = |name: &'static str| -> Counter<u64> {
|
|
267
|
-
meter.u64_counter(metric_prefix.to_string() + name).init()
|
|
268
|
-
};
|
|
269
|
-
let hst = |name: &'static str| -> Histogram<u64> {
|
|
270
|
-
meter.u64_histogram(metric_prefix.to_string() + name).init()
|
|
271
|
-
};
|
|
305
|
+
fn new_explicit(meter: TemporalMeter) -> Self {
|
|
272
306
|
Self {
|
|
273
|
-
wf_completed_counter:
|
|
274
|
-
wf_canceled_counter:
|
|
275
|
-
wf_failed_counter:
|
|
276
|
-
wf_cont_counter:
|
|
277
|
-
wf_e2e_latency:
|
|
278
|
-
wf_task_queue_poll_empty_counter:
|
|
279
|
-
wf_task_queue_poll_succeed_counter:
|
|
280
|
-
wf_task_execution_failure_counter:
|
|
281
|
-
wf_task_sched_to_start_latency:
|
|
282
|
-
wf_task_replay_latency:
|
|
283
|
-
wf_task_execution_latency:
|
|
284
|
-
act_poll_no_task:
|
|
285
|
-
act_task_received_counter:
|
|
286
|
-
act_execution_failed:
|
|
287
|
-
act_sched_to_start_latency:
|
|
288
|
-
act_exec_latency:
|
|
307
|
+
wf_completed_counter: meter.counter("workflow_completed"),
|
|
308
|
+
wf_canceled_counter: meter.counter("workflow_canceled"),
|
|
309
|
+
wf_failed_counter: meter.counter("workflow_failed"),
|
|
310
|
+
wf_cont_counter: meter.counter("workflow_continue_as_new"),
|
|
311
|
+
wf_e2e_latency: meter.histogram(WF_E2E_LATENCY_NAME),
|
|
312
|
+
wf_task_queue_poll_empty_counter: meter.counter("workflow_task_queue_poll_empty"),
|
|
313
|
+
wf_task_queue_poll_succeed_counter: meter.counter("workflow_task_queue_poll_succeed"),
|
|
314
|
+
wf_task_execution_failure_counter: meter.counter("workflow_task_execution_failed"),
|
|
315
|
+
wf_task_sched_to_start_latency: meter.histogram(WF_TASK_SCHED_TO_START_LATENCY_NAME),
|
|
316
|
+
wf_task_replay_latency: meter.histogram(WF_TASK_REPLAY_LATENCY_NAME),
|
|
317
|
+
wf_task_execution_latency: meter.histogram(WF_TASK_EXECUTION_LATENCY_NAME),
|
|
318
|
+
act_poll_no_task: meter.counter("activity_poll_no_task"),
|
|
319
|
+
act_task_received_counter: meter.counter("activity_task_received"),
|
|
320
|
+
act_execution_failed: meter.counter("activity_execution_failed"),
|
|
321
|
+
act_sched_to_start_latency: meter.histogram(ACT_SCHED_TO_START_LATENCY_NAME),
|
|
322
|
+
act_exec_latency: meter.histogram(ACT_EXEC_LATENCY_NAME),
|
|
289
323
|
// name kept as worker start for compat with old sdk / what users expect
|
|
290
|
-
worker_registered:
|
|
291
|
-
num_pollers:
|
|
292
|
-
task_slots_available:
|
|
293
|
-
sticky_cache_hit:
|
|
294
|
-
sticky_cache_miss:
|
|
295
|
-
sticky_cache_size:
|
|
324
|
+
worker_registered: meter.counter("worker_start"),
|
|
325
|
+
num_pollers: meter.histogram(NUM_POLLERS_NAME),
|
|
326
|
+
task_slots_available: meter.histogram(TASK_SLOTS_AVAILABLE_NAME),
|
|
327
|
+
sticky_cache_hit: meter.counter("sticky_cache_hit"),
|
|
328
|
+
sticky_cache_miss: meter.counter("sticky_cache_miss"),
|
|
329
|
+
sticky_cache_size: meter.histogram(STICKY_CACHE_SIZE_NAME),
|
|
296
330
|
}
|
|
297
331
|
}
|
|
298
332
|
}
|
|
@@ -30,6 +30,7 @@ use std::{
|
|
|
30
30
|
collections::VecDeque,
|
|
31
31
|
convert::TryInto,
|
|
32
32
|
env,
|
|
33
|
+
net::SocketAddr,
|
|
33
34
|
sync::{
|
|
34
35
|
atomic::{AtomicBool, Ordering},
|
|
35
36
|
Arc,
|
|
@@ -47,12 +48,10 @@ use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Layer};
|
|
|
47
48
|
const TELEM_SERVICE_NAME: &str = "temporal-core-sdk";
|
|
48
49
|
|
|
49
50
|
/// Help you construct an [EnvFilter] compatible filter string which will forward all core module
|
|
50
|
-
/// traces at `core_level` and all others (from 3rd party modules, etc) at `
|
|
51
|
+
/// traces at `core_level` and all others (from 3rd party modules, etc) at `other_level`.
|
|
51
52
|
pub fn construct_filter_string(core_level: Level, other_level: Level) -> String {
|
|
52
53
|
format!(
|
|
53
|
-
"{
|
|
54
|
-
o = other_level,
|
|
55
|
-
l = core_level
|
|
54
|
+
"{other_level},temporal_sdk_core={core_level},temporal_client={core_level},temporal_sdk={core_level}"
|
|
56
55
|
)
|
|
57
56
|
}
|
|
58
57
|
|
|
@@ -62,6 +61,7 @@ pub struct TelemetryInstance {
|
|
|
62
61
|
logs_out: Option<Mutex<CoreLogsOut>>,
|
|
63
62
|
metrics: Option<(Box<dyn MeterProvider + Send + Sync + 'static>, Meter)>,
|
|
64
63
|
trace_subscriber: Arc<dyn Subscriber + Send + Sync>,
|
|
64
|
+
prom_binding: Option<SocketAddr>,
|
|
65
65
|
_keepalive_rx: Receiver<()>,
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -71,6 +71,7 @@ impl TelemetryInstance {
|
|
|
71
71
|
logs_out: Option<Mutex<CoreLogsOut>>,
|
|
72
72
|
metric_prefix: &'static str,
|
|
73
73
|
mut meter_provider: Option<Box<dyn MeterProvider + Send + Sync + 'static>>,
|
|
74
|
+
prom_binding: Option<SocketAddr>,
|
|
74
75
|
keepalive_rx: Receiver<()>,
|
|
75
76
|
) -> Self {
|
|
76
77
|
let metrics = meter_provider.take().map(|mp| {
|
|
@@ -82,6 +83,7 @@ impl TelemetryInstance {
|
|
|
82
83
|
logs_out,
|
|
83
84
|
metrics,
|
|
84
85
|
trace_subscriber,
|
|
86
|
+
prom_binding,
|
|
85
87
|
_keepalive_rx: keepalive_rx,
|
|
86
88
|
}
|
|
87
89
|
}
|
|
@@ -91,6 +93,18 @@ impl TelemetryInstance {
|
|
|
91
93
|
pub fn trace_subscriber(&self) -> Arc<dyn Subscriber + Send + Sync> {
|
|
92
94
|
self.trace_subscriber.clone()
|
|
93
95
|
}
|
|
96
|
+
|
|
97
|
+
/// Returns the address the Prometheus server is bound to if it is running
|
|
98
|
+
pub fn prom_port(&self) -> Option<SocketAddr> {
|
|
99
|
+
self.prom_binding
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// Returns our wrapper for OTel metric meters, can be used to, ex: initialize clients
|
|
103
|
+
pub fn get_metric_meter(&self) -> Option<TemporalMeter> {
|
|
104
|
+
self.metrics
|
|
105
|
+
.as_ref()
|
|
106
|
+
.map(|(_, m)| TemporalMeter::new(m, self.metric_prefix))
|
|
107
|
+
}
|
|
94
108
|
}
|
|
95
109
|
|
|
96
110
|
thread_local! {
|
|
@@ -131,10 +145,6 @@ impl CoreTelemetry for TelemetryInstance {
|
|
|
131
145
|
vec![]
|
|
132
146
|
}
|
|
133
147
|
}
|
|
134
|
-
|
|
135
|
-
fn get_metric_meter(&self) -> Option<&Meter> {
|
|
136
|
-
self.metrics.as_ref().map(|(_, m)| m)
|
|
137
|
-
}
|
|
138
148
|
}
|
|
139
149
|
|
|
140
150
|
/// Initialize tracing subscribers/output and logging export, returning a [TelemetryInstance]
|
|
@@ -161,6 +171,7 @@ pub fn telemetry_init(opts: TelemetryOptions) -> Result<TelemetryInstance, anyho
|
|
|
161
171
|
// Parts of telem dat ====
|
|
162
172
|
let mut logs_out = None;
|
|
163
173
|
let metric_prefix = metric_prefix(&opts);
|
|
174
|
+
let mut prom_binding = None;
|
|
164
175
|
// =======================
|
|
165
176
|
|
|
166
177
|
// Tracing subscriber layers =========
|
|
@@ -210,11 +221,14 @@ pub fn telemetry_init(opts: TelemetryOptions) -> Result<TelemetryInstance, anyho
|
|
|
210
221
|
let aggregator = SDKAggSelector { metric_prefix };
|
|
211
222
|
match metrics {
|
|
212
223
|
MetricsExporter::Prometheus(addr) => {
|
|
213
|
-
let srv =
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
224
|
+
let srv = runtime.block_on(async move {
|
|
225
|
+
PromServer::new(
|
|
226
|
+
*addr,
|
|
227
|
+
aggregator,
|
|
228
|
+
metric_temporality_to_selector(opts.metric_temporality),
|
|
229
|
+
)
|
|
230
|
+
})?;
|
|
231
|
+
prom_binding = Some(srv.bound_addr());
|
|
218
232
|
let mp = srv.exporter.meter_provider()?;
|
|
219
233
|
runtime.spawn(async move { srv.run().await });
|
|
220
234
|
Some(Box::new(mp) as Box<dyn MeterProvider + Send + Sync>)
|
|
@@ -286,6 +300,7 @@ pub fn telemetry_init(opts: TelemetryOptions) -> Result<TelemetryInstance, anyho
|
|
|
286
300
|
logs_out,
|
|
287
301
|
metric_prefix,
|
|
288
302
|
meter_provider,
|
|
303
|
+
prom_binding,
|
|
289
304
|
keepalive_rx,
|
|
290
305
|
))
|
|
291
306
|
.expect("Must be able to send telem instance out of thread");
|
|
@@ -377,6 +392,7 @@ pub mod test_initters {
|
|
|
377
392
|
.unwrap();
|
|
378
393
|
}
|
|
379
394
|
}
|
|
395
|
+
use crate::telemetry::metrics::TemporalMeter;
|
|
380
396
|
#[cfg(test)]
|
|
381
397
|
pub use test_initters::*;
|
|
382
398
|
|