temporalio 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +175 -4
  3. data/bridge/Cargo.lock +44 -21
  4. data/bridge/Cargo.toml +1 -0
  5. data/bridge/sdk-core/Cargo.toml +1 -1
  6. data/bridge/sdk-core/README.md +1 -4
  7. data/bridge/sdk-core/client/Cargo.toml +1 -1
  8. data/bridge/sdk-core/client/src/lib.rs +12 -20
  9. data/bridge/sdk-core/client/src/raw.rs +9 -8
  10. data/bridge/sdk-core/client/src/retry.rs +100 -23
  11. data/bridge/sdk-core/core/Cargo.toml +7 -7
  12. data/bridge/sdk-core/core/benches/workflow_replay.rs +13 -10
  13. data/bridge/sdk-core/core/src/abstractions.rs +22 -22
  14. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +146 -43
  15. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +419 -9
  16. data/bridge/sdk-core/core/src/core_tests/queries.rs +247 -89
  17. data/bridge/sdk-core/core/src/core_tests/workers.rs +2 -2
  18. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
  19. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +47 -27
  20. data/bridge/sdk-core/core/src/lib.rs +139 -32
  21. data/bridge/sdk-core/core/src/protosext/mod.rs +1 -1
  22. data/bridge/sdk-core/core/src/replay/mod.rs +185 -41
  23. data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
  24. data/bridge/sdk-core/core/src/telemetry/metrics.rs +184 -139
  25. data/bridge/sdk-core/core/src/telemetry/mod.rs +310 -315
  26. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +4 -3
  27. data/bridge/sdk-core/core/src/test_help/mod.rs +23 -9
  28. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +12 -6
  29. data/bridge/sdk-core/core/src/worker/activities.rs +40 -23
  30. data/bridge/sdk-core/core/src/worker/client/mocks.rs +1 -1
  31. data/bridge/sdk-core/core/src/worker/client.rs +30 -4
  32. data/bridge/sdk-core/core/src/worker/mod.rs +23 -19
  33. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +10 -19
  34. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +99 -25
  35. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -5
  36. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -5
  37. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -5
  38. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +3 -5
  39. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -5
  40. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +2 -6
  41. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -5
  42. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +24 -22
  43. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -38
  44. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
  45. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -5
  46. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -5
  47. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -5
  48. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +8 -2
  49. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +1 -5
  50. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +1 -1
  51. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +233 -217
  52. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +1 -6
  53. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +4 -4
  54. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +13 -5
  55. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +86 -29
  56. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +2 -2
  57. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +56 -11
  58. data/bridge/sdk-core/core-api/Cargo.toml +4 -3
  59. data/bridge/sdk-core/core-api/src/lib.rs +1 -43
  60. data/bridge/sdk-core/core-api/src/telemetry.rs +147 -0
  61. data/bridge/sdk-core/core-api/src/worker.rs +13 -0
  62. data/bridge/sdk-core/etc/deps.svg +115 -140
  63. data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
  64. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  65. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  66. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  67. data/bridge/sdk-core/protos/api_upstream/buf.yaml +0 -3
  68. data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
  69. data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
  70. data/bridge/sdk-core/protos/api_upstream/{temporal/api/update/v1/message.proto → build/tools.go} +6 -23
  71. data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
  72. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +12 -9
  73. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +20 -19
  74. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +2 -2
  75. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  76. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +4 -4
  77. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  78. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +5 -3
  79. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +23 -2
  80. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/{cluster.proto → interaction_type.proto} +10 -11
  81. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  82. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  83. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  84. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  85. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  86. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +2 -13
  87. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  88. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  89. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  90. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  91. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +26 -19
  92. data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +87 -0
  93. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -2
  94. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +21 -61
  95. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -21
  96. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  97. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  98. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +110 -31
  99. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +4 -4
  100. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  101. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +3 -2
  102. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -16
  103. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +17 -3
  104. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  105. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +8 -1
  106. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  107. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  108. data/bridge/sdk-core/sdk/Cargo.toml +2 -2
  109. data/bridge/sdk-core/sdk/src/interceptors.rs +36 -3
  110. data/bridge/sdk-core/sdk/src/lib.rs +7 -5
  111. data/bridge/sdk-core/sdk/src/workflow_context.rs +13 -2
  112. data/bridge/sdk-core/sdk/src/workflow_future.rs +3 -7
  113. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +1 -1
  114. data/bridge/sdk-core/sdk-core-protos/build.rs +0 -1
  115. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +65 -18
  116. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +22 -22
  117. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +104 -44
  118. data/bridge/sdk-core/test-utils/Cargo.toml +2 -1
  119. data/bridge/sdk-core/test-utils/src/lib.rs +81 -29
  120. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -2
  121. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
  122. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +0 -13
  123. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +167 -13
  124. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
  125. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +106 -20
  126. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +18 -8
  127. data/bridge/sdk-core/tests/main.rs +6 -4
  128. data/bridge/src/connection.rs +81 -62
  129. data/bridge/src/lib.rs +92 -33
  130. data/bridge/src/runtime.rs +9 -2
  131. data/bridge/src/worker.rs +53 -2
  132. data/lib/bridge.so +0 -0
  133. data/lib/gen/temporal/api/batch/v1/message_pb.rb +8 -6
  134. data/lib/gen/temporal/api/command/v1/message_pb.rb +17 -9
  135. data/lib/gen/temporal/api/common/v1/message_pb.rb +1 -1
  136. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +2 -1
  137. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +3 -1
  138. data/lib/gen/temporal/api/enums/v1/common_pb.rb +2 -1
  139. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +3 -2
  140. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +7 -1
  141. data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +25 -0
  142. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +1 -1
  143. data/lib/gen/temporal/api/enums/v1/query_pb.rb +1 -1
  144. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +1 -1
  145. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +1 -1
  146. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +1 -1
  147. data/lib/gen/temporal/api/enums/v1/update_pb.rb +1 -6
  148. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +1 -1
  149. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +1 -1
  150. data/lib/gen/temporal/api/failure/v1/message_pb.rb +1 -1
  151. data/lib/gen/temporal/api/filter/v1/message_pb.rb +1 -1
  152. data/lib/gen/temporal/api/history/v1/message_pb.rb +19 -18
  153. data/lib/gen/temporal/api/interaction/v1/message_pb.rb +49 -0
  154. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +1 -1
  155. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +11 -51
  156. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +1 -1
  157. data/lib/gen/temporal/api/query/v1/message_pb.rb +1 -1
  158. data/lib/gen/temporal/api/replication/v1/message_pb.rb +1 -1
  159. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +22 -1
  160. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +2 -2
  161. data/lib/gen/temporal/api/version/v1/message_pb.rb +1 -1
  162. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +2 -1
  163. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +27 -10
  164. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +1 -1
  165. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +1 -0
  166. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +5 -1
  167. data/lib/temporalio/activity/context.rb +97 -0
  168. data/lib/temporalio/activity/info.rb +67 -0
  169. data/lib/temporalio/activity.rb +85 -0
  170. data/lib/temporalio/bridge/error.rb +8 -0
  171. data/lib/temporalio/bridge.rb +14 -0
  172. data/lib/{temporal → temporalio}/client/implementation.rb +49 -48
  173. data/lib/{temporal → temporalio}/client/workflow_handle.rb +35 -35
  174. data/lib/{temporal → temporalio}/client.rb +19 -32
  175. data/lib/{temporal → temporalio}/connection.rb +238 -223
  176. data/lib/{temporal → temporalio}/data_converter.rb +76 -35
  177. data/lib/{temporal → temporalio}/error/failure.rb +6 -6
  178. data/lib/{temporal → temporalio}/error/workflow_failure.rb +4 -2
  179. data/lib/{temporal → temporalio}/errors.rb +19 -1
  180. data/lib/{temporal → temporalio}/failure_converter/base.rb +5 -5
  181. data/lib/{temporal → temporalio}/failure_converter/basic.rb +58 -52
  182. data/lib/temporalio/failure_converter.rb +7 -0
  183. data/lib/{temporal → temporalio}/interceptor/chain.rb +2 -1
  184. data/lib/{temporal → temporalio}/interceptor/client.rb +22 -1
  185. data/lib/{temporal → temporalio}/payload_codec/base.rb +5 -5
  186. data/lib/{temporal → temporalio}/payload_converter/base.rb +3 -3
  187. data/lib/{temporal → temporalio}/payload_converter/bytes.rb +4 -3
  188. data/lib/{temporal → temporalio}/payload_converter/composite.rb +7 -5
  189. data/lib/{temporal → temporalio}/payload_converter/encoding_base.rb +4 -4
  190. data/lib/{temporal → temporalio}/payload_converter/json.rb +4 -3
  191. data/lib/{temporal → temporalio}/payload_converter/nil.rb +4 -3
  192. data/lib/temporalio/payload_converter.rb +14 -0
  193. data/lib/{temporal → temporalio}/retry_policy.rb +4 -4
  194. data/lib/{temporal → temporalio}/retry_state.rb +1 -1
  195. data/lib/temporalio/runtime.rb +25 -0
  196. data/lib/{temporal → temporalio}/timeout_type.rb +2 -2
  197. data/lib/temporalio/version.rb +3 -0
  198. data/lib/temporalio/worker/activity_runner.rb +92 -0
  199. data/lib/temporalio/worker/activity_worker.rb +138 -0
  200. data/lib/temporalio/worker/reactor.rb +46 -0
  201. data/lib/temporalio/worker/runner.rb +63 -0
  202. data/lib/temporalio/worker/sync_worker.rb +88 -0
  203. data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
  204. data/lib/temporalio/worker.rb +198 -0
  205. data/lib/{temporal → temporalio}/workflow/execution_info.rb +4 -4
  206. data/lib/{temporal → temporalio}/workflow/execution_status.rb +1 -1
  207. data/lib/{temporal → temporalio}/workflow/id_reuse_policy.rb +6 -6
  208. data/lib/{temporal → temporalio}/workflow/query_reject_condition.rb +5 -5
  209. data/lib/temporalio.rb +12 -3
  210. data/temporalio.gemspec +7 -3
  211. metadata +79 -56
  212. data/bridge/sdk-core/bridge-ffi/Cargo.toml +0 -24
  213. data/bridge/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  214. data/bridge/sdk-core/bridge-ffi/build.rs +0 -25
  215. data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -249
  216. data/bridge/sdk-core/bridge-ffi/src/lib.rs +0 -825
  217. data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +0 -211
  218. data/bridge/sdk-core/core/src/log_export.rs +0 -62
  219. data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
  220. data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
  221. data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
  222. data/bridge/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  223. data/bridge/sdk-core/sdk/src/conversions.rs +0 -8
  224. data/lib/gen/temporal/api/cluster/v1/message_pb.rb +0 -67
  225. data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +0 -26
  226. data/lib/gen/temporal/api/update/v1/message_pb.rb +0 -26
  227. data/lib/temporal/bridge.rb +0 -14
  228. data/lib/temporal/failure_converter.rb +0 -8
  229. data/lib/temporal/payload_converter.rb +0 -14
  230. data/lib/temporal/runtime.rb +0 -22
  231. data/lib/temporal/version.rb +0 -3
  232. data/lib/temporal.rb +0 -8
@@ -357,6 +357,7 @@ impl ManagedRun {
357
357
  let query_responses = data.query_responses;
358
358
  let has_query_responses = !query_responses.is_empty();
359
359
  let is_query_playback = data.has_pending_query && !has_query_responses;
360
+ let mut force_new_wft = due_to_heartbeat_timeout;
360
361
 
361
362
  // We only actually want to send commands back to the server if there are no more
362
363
  // pending activations and we are caught up on replay. We don't want to complete a wft
@@ -366,19 +367,26 @@ impl ManagedRun {
366
367
  // either.
367
368
  let no_commands_and_evicting =
368
369
  outgoing_cmds.commands.is_empty() && data.activation_was_only_eviction;
370
+ let should_respond = !(self.wfm.machines.has_pending_jobs()
371
+ || outgoing_cmds.replaying
372
+ || is_query_playback
373
+ || no_commands_and_evicting);
374
+ // If there are pending LA resolutions, and we're responding to a query here,
375
+ // we want to make sure to force a new task, as otherwise once we tell lang about
376
+ // the LA resolution there wouldn't be any task to reply to with the result of iterating
377
+ // the workflow.
378
+ if has_query_responses && self.wfm.machines.has_pending_la_resolutions() {
379
+ force_new_wft = true;
380
+ }
369
381
  let to_be_sent = ServerCommandsWithWorkflowInfo {
370
382
  task_token: data.task_token,
371
383
  action: ActivationAction::WftComplete {
372
- force_new_wft: due_to_heartbeat_timeout,
384
+ force_new_wft,
373
385
  commands: outgoing_cmds.commands,
374
386
  query_responses,
375
387
  },
376
388
  };
377
389
 
378
- let should_respond = !(self.wfm.machines.has_pending_jobs()
379
- || outgoing_cmds.replaying
380
- || is_query_playback
381
- || no_commands_and_evicting);
382
390
  let outcome = if should_respond || has_query_responses {
383
391
  ActivationCompleteOutcome::ReportWFTSuccess(to_be_sent)
384
392
  } else {
@@ -24,7 +24,7 @@ use crate::{
24
24
  telemetry::VecDisplayer,
25
25
  worker::{
26
26
  activities::{ActivitiesFromWFTsHandle, PermittedTqResp},
27
- client::WorkerClient,
27
+ client::{WorkerClient, WorkflowTaskCompletion},
28
28
  workflow::{
29
29
  managed_run::{ManagedRun, WorkflowManager},
30
30
  wft_poller::validate_wft,
@@ -36,6 +36,7 @@ use crate::{
36
36
  };
37
37
  use futures::{stream::BoxStream, Stream, StreamExt};
38
38
  use std::{
39
+ collections::HashSet,
39
40
  fmt::{Debug, Display, Formatter},
40
41
  future::Future,
41
42
  ops::DerefMut,
@@ -43,12 +44,12 @@ use std::{
43
44
  sync::Arc,
44
45
  time::{Duration, Instant},
45
46
  };
46
- use temporal_client::WorkflowTaskCompletion;
47
47
  use temporal_sdk_core_api::errors::{CompleteWfError, PollWfError};
48
48
  use temporal_sdk_core_protos::{
49
49
  coresdk::{
50
50
  workflow_activation::{
51
- remove_from_cache::EvictionReason, QueryWorkflow, WorkflowActivation,
51
+ remove_from_cache::EvictionReason, workflow_activation_job, QueryWorkflow,
52
+ WorkflowActivation, WorkflowActivationJob,
52
53
  },
53
54
  workflow_commands::*,
54
55
  workflow_completion,
@@ -78,6 +79,7 @@ use tokio_util::sync::CancellationToken;
78
79
  use tracing::Span;
79
80
 
80
81
  pub(crate) const LEGACY_QUERY_ID: &str = "legacy_query";
82
+ const MAX_EAGER_ACTIVITY_RESERVATIONS_PER_WORKFLOW_TASK: usize = 3;
81
83
 
82
84
  type Result<T, E = WFMachinesError> = result::Result<T, E>;
83
85
  type BoxedActivationStream = BoxStream<'static, Result<ActivationOrAuto, PollWfError>>;
@@ -107,6 +109,7 @@ pub(super) struct WorkflowBasics {
107
109
  pub metrics: MetricsContext,
108
110
  pub namespace: String,
109
111
  pub task_queue: String,
112
+ pub ignore_evicts_on_shutdown: bool,
110
113
  }
111
114
 
112
115
  impl Workflows {
@@ -179,7 +182,7 @@ impl Workflows {
179
182
  }
180
183
  stream.next().await.unwrap_or(Err(PollWfError::ShutDown))?
181
184
  };
182
- Span::current().record("run_id", &r.run_id());
185
+ Span::current().record("run_id", r.run_id());
183
186
  match r {
184
187
  ActivationOrAuto::LangActivation(act) | ActivationOrAuto::ReadyForQueries(act) => {
185
188
  debug!(activation=%act, "Sending activation to lang");
@@ -457,30 +460,34 @@ impl Workflows {
457
460
  commands: &mut [Command],
458
461
  ) -> Vec<OwnedMeteredSemPermit> {
459
462
  let mut reserved = vec![];
460
- if let Some(at_handle) = self.activity_tasks_handle.as_ref() {
461
- for cmd in commands {
462
- if let Some(Attributes::ScheduleActivityTaskCommandAttributes(attrs)) =
463
- cmd.attributes.as_mut()
464
- {
465
- // If request_eager_execution was already false, that means lang explicitly
466
- // told us it didn't want to eagerly execute for some reason. So, we only
467
- // ever turn *off* eager execution if a slot is not available or the activity
468
- // is scheduled on a different task queue.
469
- if attrs.request_eager_execution {
470
- let same_task_queue = attrs
471
- .task_queue
463
+ for cmd in commands {
464
+ if let Some(Attributes::ScheduleActivityTaskCommandAttributes(attrs)) =
465
+ cmd.attributes.as_mut()
466
+ {
467
+ // If request_eager_execution was already false, that means lang explicitly
468
+ // told us it didn't want to eagerly execute for some reason. So, we only
469
+ // ever turn *off* eager execution if a slot is not available or the activity
470
+ // is scheduled on a different task queue.
471
+ if attrs.request_eager_execution {
472
+ let same_task_queue = attrs
473
+ .task_queue
474
+ .as_ref()
475
+ .map(|q| q.name == self.task_queue)
476
+ .unwrap_or_default();
477
+ if same_task_queue
478
+ && reserved.len() < MAX_EAGER_ACTIVITY_RESERVATIONS_PER_WORKFLOW_TASK
479
+ {
480
+ if let Some(p) = self
481
+ .activity_tasks_handle
472
482
  .as_ref()
473
- .map(|q| q.name == self.task_queue)
474
- .unwrap_or_default();
475
- if same_task_queue {
476
- if let Some(p) = at_handle.reserve_slot() {
477
- reserved.push(p);
478
- } else {
479
- attrs.request_eager_execution = false;
480
- }
483
+ .and_then(|h| h.reserve_slot())
484
+ {
485
+ reserved.push(p);
481
486
  } else {
482
487
  attrs.request_eager_execution = false;
483
488
  }
489
+ } else {
490
+ attrs.request_eager_execution = false;
484
491
  }
485
492
  }
486
493
  }
@@ -543,6 +550,11 @@ struct ManagedRunHandle {
543
550
  run_actions_tx: UnboundedSender<RunAction>,
544
551
  /// Handle to the task where the actual machines live
545
552
  handle: JoinHandle<()>,
553
+
554
+ /// We track if we have recorded useful debugging values onto a certain span yet, to overcome
555
+ /// duplicating field values. Remove this once https://github.com/tokio-rs/tracing/issues/2334
556
+ /// is fixed.
557
+ recorded_span_ids: HashSet<tracing::Id>,
546
558
  metrics: MetricsContext,
547
559
  }
548
560
  impl ManagedRunHandle {
@@ -564,9 +576,10 @@ impl ManagedRunHandle {
564
576
  more_pending_work: false,
565
577
  trying_to_evict: None,
566
578
  last_action_acked: true,
579
+ run_actions_tx,
567
580
  handle,
581
+ recorded_span_ids: Default::default(),
568
582
  metrics,
569
- run_actions_tx,
570
583
  }
571
584
  }
572
585
 
@@ -767,6 +780,11 @@ impl OutstandingActivation {
767
780
  pub struct WorkflowTaskInfo {
768
781
  pub task_token: TaskToken,
769
782
  pub attempt: u32,
783
+ /// Exists to allow easy tagging of spans with workflow ids. Is duplicative of info inside the
784
+ /// run machines themselves, but that can't be accessed easily. Would be nice to somehow have a
785
+ /// shared repository, or refcounts, or whatever, for strings like these that get duped all
786
+ /// sorts of places.
787
+ pub wf_id: String,
770
788
  }
771
789
 
772
790
  #[derive(Debug)]
@@ -887,10 +905,12 @@ fn validate_completion(
887
905
  )
888
906
  {
889
907
  return Err(CompleteWfError::MalformedWorkflowCompletion {
890
- reason: "Workflow completion had a legacy query response along with other \
891
- commands. This is not allowed and constitutes an error in the \
892
- lang SDK"
893
- .to_owned(),
908
+ reason: format!(
909
+ "Workflow completion had a legacy query response along with other \
910
+ commands. This is not allowed and constitutes an error in the \
911
+ lang SDK. Commands: {:?}",
912
+ commands
913
+ ),
894
914
  run_id: completion.run_id,
895
915
  });
896
916
  }
@@ -988,6 +1008,14 @@ enum RunUpdateResponseKind {
988
1008
  Good(GoodRunUpdate),
989
1009
  Fail(FailRunUpdate),
990
1010
  }
1011
+ impl RunUpdateResponseKind {
1012
+ pub(crate) fn run_id(&self) -> &str {
1013
+ match self {
1014
+ RunUpdateResponseKind::Good(g) => &g.run_id,
1015
+ RunUpdateResponseKind::Fail(f) => &f.run_id,
1016
+ }
1017
+ }
1018
+ }
991
1019
 
992
1020
  #[derive(Debug)]
993
1021
  struct GoodRunUpdate {
@@ -1073,6 +1101,7 @@ pub enum WFCommand {
1073
1101
  SignalExternalWorkflow(SignalExternalWorkflowExecution),
1074
1102
  CancelSignalWorkflow(CancelSignalWorkflow),
1075
1103
  UpsertSearchAttributes(UpsertWorkflowSearchAttributes),
1104
+ ModifyWorkflowProperties(ModifyWorkflowProperties),
1076
1105
  }
1077
1106
 
1078
1107
  impl TryFrom<WorkflowCommand> for WFCommand {
@@ -1114,6 +1143,9 @@ impl TryFrom<WorkflowCommand> for WFCommand {
1114
1143
  workflow_command::Variant::UpsertWorkflowSearchAttributes(s) => {
1115
1144
  Ok(Self::UpsertSearchAttributes(s))
1116
1145
  }
1146
+ workflow_command::Variant::ModifyWorkflowProperties(s) => {
1147
+ Ok(Self::ModifyWorkflowProperties(s))
1148
+ }
1117
1149
  }
1118
1150
  }
1119
1151
  }
@@ -1141,3 +1173,28 @@ pub struct WorkflowStartedInfo {
1141
1173
 
1142
1174
  type LocalActivityRequestSink =
1143
1175
  Arc<dyn Fn(Vec<LocalActRequest>) -> Vec<LocalActivityResolution> + Send + Sync>;
1176
+
1177
+ /// Wraps outgoing activation job protos with some internal details core might care about
1178
+ #[derive(Debug, derive_more::Display)]
1179
+ #[display(fmt = "{}", variant)]
1180
+ struct OutgoingJob {
1181
+ variant: workflow_activation_job::Variant,
1182
+ /// Since LA resolutions are not distinguished from non-LA resolutions as far as lang is
1183
+ /// concerned, but core cares about that sometimes, attach that info here.
1184
+ is_la_resolution: bool,
1185
+ }
1186
+ impl<WA: Into<workflow_activation_job::Variant>> From<WA> for OutgoingJob {
1187
+ fn from(wa: WA) -> Self {
1188
+ Self {
1189
+ variant: wa.into(),
1190
+ is_la_resolution: false,
1191
+ }
1192
+ }
1193
+ }
1194
+ impl From<OutgoingJob> for WorkflowActivationJob {
1195
+ fn from(og: OutgoingJob) -> Self {
1196
+ Self {
1197
+ variant: Some(og.variant),
1198
+ }
1199
+ }
1200
+ }
@@ -69,7 +69,7 @@ mod tests {
69
69
  .times(1)
70
70
  .returning(|| Some(Ok(PollWorkflowTaskQueueResponse::default())));
71
71
  mock_poller.expect_poll().times(1).returning(|| None);
72
- let stream = new_wft_poller(Box::new(mock_poller), Default::default());
72
+ let stream = new_wft_poller(Box::new(mock_poller), MetricsContext::no_op());
73
73
  pin_mut!(stream);
74
74
  assert_matches!(stream.next().await, None);
75
75
  }
@@ -81,7 +81,7 @@ mod tests {
81
81
  .expect_poll()
82
82
  .times(1)
83
83
  .returning(|| Some(Err(tonic::Status::internal("ahhh"))));
84
- let stream = new_wft_poller(Box::new(mock_poller), Default::default());
84
+ let stream = new_wft_poller(Box::new(mock_poller), MetricsContext::no_op());
85
85
  pin_mut!(stream);
86
86
  assert_matches!(stream.next().await, Some(Err(_)));
87
87
  }
@@ -41,9 +41,27 @@ pub(crate) struct WFStream {
41
41
  /// Ensures we stay at or below this worker's maximum concurrent workflow task limit
42
42
  wft_semaphore: MeteredSemaphore,
43
43
  shutdown_token: CancellationToken,
44
+ ignore_evicts_on_shutdown: bool,
44
45
 
45
46
  metrics: MetricsContext,
46
47
  }
48
+ impl WFStream {
49
+ fn record_span_fields(&mut self, run_id: &str, span: &Span) {
50
+ if let Some(run_handle) = self.runs.get_mut(run_id) {
51
+ if let Some(spid) = span.id() {
52
+ if run_handle.recorded_span_ids.contains(&spid) {
53
+ return;
54
+ }
55
+ run_handle.recorded_span_ids.insert(spid);
56
+
57
+ if let Some(wid) = run_handle.wft.as_ref().map(|wft| &wft.info.wf_id) {
58
+ span.record("workflow_id", wid.as_str());
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+
47
65
  /// All possible inputs to the [WFStream]
48
66
  #[derive(derive_more::From, Debug)]
49
67
  enum WFStreamInput {
@@ -81,6 +99,18 @@ pub(super) enum LocalInputs {
81
99
  RequestEviction(RequestEvictMsg),
82
100
  GetStateInfo(GetStateInfoMsg),
83
101
  }
102
+ impl LocalInputs {
103
+ fn run_id(&self) -> Option<&str> {
104
+ Some(match self {
105
+ LocalInputs::Completion(c) => c.completion.run_id(),
106
+ LocalInputs::LocalResolution(lr) => &lr.run_id,
107
+ LocalInputs::PostActivation(pa) => &pa.run_id,
108
+ LocalInputs::RunUpdateResponse(rur) => rur.run_id(),
109
+ LocalInputs::RequestEviction(re) => &re.run_id,
110
+ LocalInputs::GetStateInfo(_) => return None,
111
+ })
112
+ }
113
+ }
84
114
  #[derive(Debug, derive_more::From)]
85
115
  #[allow(clippy::large_enum_variant)] // PollerDead only ever gets used once, so not important.
86
116
  enum ExternalPollerInputs {
@@ -130,10 +160,9 @@ impl WFStream {
130
160
  MetricsContext::available_task_slots,
131
161
  );
132
162
  let wft_sem_clone = wft_semaphore.clone();
133
- let proceeder = move || {
134
- let wft_sem_clone = wft_sem_clone.clone();
135
- async move { wft_sem_clone.acquire_owned().await.unwrap() }
136
- };
163
+ let proceeder = stream::unfold(wft_sem_clone, |sem| async move {
164
+ Some((sem.acquire_owned().await.unwrap(), sem))
165
+ });
137
166
  let poller_wfts = stream_when_allowed(external_wfts, proceeder);
138
167
  let (run_update_tx, run_update_rx) = unbounded_channel();
139
168
  let local_rx = stream::select(
@@ -165,6 +194,7 @@ impl WFStream {
165
194
  client,
166
195
  wft_semaphore,
167
196
  shutdown_token: basics.shutdown_token,
197
+ ignore_evicts_on_shutdown: basics.ignore_evicts_on_shutdown,
168
198
  metrics: basics.metrics,
169
199
  };
170
200
  all_inputs
@@ -180,6 +210,9 @@ impl WFStream {
180
210
  }
181
211
  WFStreamInput::Local(local_input) => {
182
212
  let _span_g = local_input.span.enter();
213
+ if let Some(rid) = local_input.input.run_id() {
214
+ state.record_span_fields(rid, &local_input.span);
215
+ }
183
216
  match local_input.input {
184
217
  LocalInputs::RunUpdateResponse(resp) => {
185
218
  state.process_run_update_response(resp)
@@ -281,7 +314,7 @@ impl WFStream {
281
314
  // If there are in-poll queries, insert jobs for those queries into the
282
315
  // activation, but only if we hit the cache. If we didn't, those queries
283
316
  // will need to be dealt with once replay is over
284
- if !wft.pending_queries.is_empty() && wft.hit_cache {
317
+ if wft.hit_cache {
285
318
  put_queries_in_act(&mut activation, wft);
286
319
  }
287
320
  }
@@ -376,8 +409,9 @@ impl WFStream {
376
409
  }
377
410
  }
378
411
 
379
- #[instrument(level = "debug", skip(self, pwft),
380
- fields(run_id=%pwft.wft.workflow_execution.run_id))]
412
+ #[instrument(skip(self, pwft),
413
+ fields(run_id=%pwft.wft.workflow_execution.run_id,
414
+ workflow_id=%pwft.wft.workflow_execution.workflow_id))]
381
415
  fn instantiate_or_update(&mut self, pwft: PermittedWFT) {
382
416
  let (mut work, permit) = if let Some(w) = self.buffer_resp_if_outstanding_work(pwft) {
383
417
  (w.wft, w.permit)
@@ -407,6 +441,7 @@ impl WFStream {
407
441
  let wft_info = WorkflowTaskInfo {
408
442
  attempt: work.attempt,
409
443
  task_token: work.task_token,
444
+ wf_id: work.workflow_execution.workflow_id.clone(),
410
445
  };
411
446
  let poll_resp_is_incremental = work
412
447
  .history
@@ -476,8 +511,6 @@ impl WFStream {
476
511
  })
477
512
  }
478
513
 
479
- #[instrument(level = "debug", skip(self, complete),
480
- fields(run_id=%complete.completion.run_id()))]
481
514
  fn process_completion(&mut self, complete: WFActCompleteMsg) {
482
515
  match complete.completion {
483
516
  ValidatedCompletion::Success { run_id, commands } => {
@@ -691,7 +724,7 @@ impl WFStream {
691
724
  EvictionRequestResult::EvictionAlreadyRequested(attempts)
692
725
  }
693
726
  } else {
694
- warn!(run_id=%info.run_id, "Eviction requested for unknown run");
727
+ debug!(run_id=%info.run_id, "Eviction requested for unknown run");
695
728
  EvictionRequestResult::NotFound
696
729
  }
697
730
  }
@@ -875,7 +908,7 @@ impl WFStream {
875
908
  let all_runs_ready = self
876
909
  .runs
877
910
  .handles()
878
- .all(|r| !r.has_any_pending_work(true, false));
911
+ .all(|r| !r.has_any_pending_work(self.ignore_evicts_on_shutdown, false));
879
912
  if self.shutdown_token.is_cancelled() && all_runs_ready {
880
913
  info!("Workflow shutdown is done");
881
914
  true
@@ -931,6 +964,18 @@ impl WFStream {
931
964
 
932
965
  /// Drains pending queries from the workflow task and appends them to the activation's jobs
933
966
  fn put_queries_in_act(act: &mut WorkflowActivation, wft: &mut OutstandingTask) {
967
+ // Nothing to do if there are no pending queries
968
+ if wft.pending_queries.is_empty() {
969
+ return;
970
+ }
971
+
972
+ let has_legacy = wft.has_pending_legacy_query();
973
+ // Cannot dispatch legacy query if there are any other jobs - which can happen if, ex, a local
974
+ // activity resolves while we've gotten a legacy query after heartbeating.
975
+ if has_legacy && !act.jobs.is_empty() {
976
+ return;
977
+ }
978
+
934
979
  debug!(queries=?wft.pending_queries, "Dispatching queries");
935
980
  let query_jobs = wft
936
981
  .pending_queries
@@ -13,14 +13,15 @@ categories = ["development-tools"]
13
13
  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
14
14
 
15
15
  [dependencies]
16
- anyhow = "1.0"
17
16
  async-trait = "0.1"
18
- derive_builder = "0.11"
19
- log = "0.4"
17
+ derive_builder = "0.12"
20
18
  opentelemetry = "0.18"
21
19
  prost-types = "0.11"
20
+ serde_json = "1.0"
22
21
  thiserror = "1.0"
23
22
  tonic = "0.8"
23
+ tracing-core = "0.1"
24
+ url = "2.3"
24
25
 
25
26
  [dependencies.temporal-sdk-core-protos]
26
27
  path = "../sdk-core-protos"
@@ -1,13 +1,11 @@
1
1
  pub mod errors;
2
+ pub mod telemetry;
2
3
  pub mod worker;
3
4
 
4
5
  use crate::{
5
6
  errors::{CompleteActivityError, CompleteWfError, PollActivityError, PollWfError},
6
7
  worker::WorkerConfig,
7
8
  };
8
- use log::Level;
9
- use opentelemetry::metrics::Meter;
10
- use std::time::{Duration, SystemTime, UNIX_EPOCH};
11
9
  use temporal_sdk_core_protos::coresdk::{
12
10
  activity_task::ActivityTask, workflow_activation::WorkflowActivation,
13
11
  workflow_completion::WorkflowActivationCompletion, ActivityHeartbeat, ActivityTaskCompletion,
@@ -109,43 +107,3 @@ pub trait Worker: Send + Sync {
109
107
  /// This should be called only after [Worker::shutdown] has resolved.
110
108
  async fn finalize_shutdown(self);
111
109
  }
112
-
113
- /// Should be backed by a process-wide singleton who is responsible for telemetry and logging
114
- /// management.
115
- pub trait CoreTelemetry {
116
- /// Core buffers logs that should be shuttled over to lang so that they may be rendered with
117
- /// the user's desired logging library. Use this function to grab the most recent buffered logs
118
- /// since the last time it was called. A fixed number of such logs are retained at maximum, with
119
- /// the oldest being dropped when full.
120
- ///
121
- /// Returns the list of logs from oldest to newest. Returns an empty vec if the feature is not
122
- /// configured.
123
- fn fetch_buffered_logs(&self) -> Vec<CoreLog>;
124
-
125
- /// If metrics gathering is enabled, returns the OTel meter for core telemetry, which can be
126
- /// used to create metrics instruments, or passed to things that create/record metrics (ex:
127
- /// clients).
128
- fn get_metric_meter(&self) -> Option<&Meter>;
129
- }
130
-
131
- /// A log line (which ultimately came from a tracing event) exported from Core->Lang
132
- #[derive(Debug)]
133
- pub struct CoreLog {
134
- /// Log message
135
- pub message: String,
136
- /// Time log was generated (not when it was exported to lang)
137
- pub timestamp: SystemTime,
138
- /// Message level
139
- pub level: Level,
140
- // KV pairs aren't meaningfully exposed yet to the log interface by tracing
141
- }
142
-
143
- impl CoreLog {
144
- /// Return timestamp as ms since epoch
145
- pub fn millis_since_epoch(&self) -> u128 {
146
- self.timestamp
147
- .duration_since(UNIX_EPOCH)
148
- .unwrap_or(Duration::ZERO)
149
- .as_millis()
150
- }
151
- }
@@ -0,0 +1,147 @@
1
+ use opentelemetry::metrics::Meter;
2
+ use std::{
3
+ collections::HashMap,
4
+ net::SocketAddr,
5
+ time::{Duration, SystemTime, UNIX_EPOCH},
6
+ };
7
+ use tracing_core::Level;
8
+ use url::Url;
9
+
10
+ /// Each core runtime instance has a telemetry subsystem associated with it, this trait defines the
11
+ /// operations that lang might want to perform on that telemetry after it's initialized.
12
+ pub trait CoreTelemetry {
13
+ /// Each worker buffers logs that should be shuttled over to lang so that they may be rendered
14
+ /// with the user's desired logging library. Use this function to grab the most recent buffered
15
+ /// logs since the last time it was called. A fixed number of such logs are retained at maximum,
16
+ /// with the oldest being dropped when full.
17
+ ///
18
+ /// Returns the list of logs from oldest to newest. Returns an empty vec if the feature is not
19
+ /// configured.
20
+ fn fetch_buffered_logs(&self) -> Vec<CoreLog>;
21
+
22
+ /// If metrics gathering is enabled, returns the OTel meter for core telemetry, which can be
23
+ /// used to create metrics instruments, or passed to things that create/record metrics (ex:
24
+ /// clients).
25
+ fn get_metric_meter(&self) -> Option<&Meter>;
26
+ }
27
+
28
+ /// Telemetry configuration options. Construct with [TelemetryOptionsBuilder]
29
+ #[derive(Debug, Clone, derive_builder::Builder)]
30
+ #[non_exhaustive]
31
+ pub struct TelemetryOptions {
32
+ /// Optional trace exporter - set as None to disable.
33
+ #[builder(setter(into, strip_option), default)]
34
+ pub tracing: Option<TraceExportConfig>,
35
+ /// Optional logger - set as None to disable.
36
+ #[builder(setter(into, strip_option), default)]
37
+ pub logging: Option<Logger>,
38
+ /// Optional metrics exporter - set as None to disable.
39
+ #[builder(setter(into, strip_option), default)]
40
+ pub metrics: Option<MetricsExporter>,
41
+
42
+ /// If set true, do not prefix metrics with `temporal_`. Will be removed eventually as
43
+ /// the prefix is consistent with other SDKs.
44
+ #[builder(default)]
45
+ pub no_temporal_prefix_for_metrics: bool,
46
+
47
+ /// Specifies the aggregation temporality for metric export. Defaults to cumulative.
48
+ #[builder(default = "MetricTemporality::Cumulative")]
49
+ pub metric_temporality: MetricTemporality,
50
+ }
51
+
52
+ /// Options for exporting to an OpenTelemetry Collector
53
+ #[derive(Debug, Clone)]
54
+ pub struct OtelCollectorOptions {
55
+ /// The url of the OTel collector to export telemetry and metrics to. Lang SDK should also
56
+ /// export to this same collector.
57
+ pub url: Url,
58
+ /// Optional set of HTTP headers to send to the Collector, e.g for authentication.
59
+ pub headers: HashMap<String, String>,
60
+ /// Optionally specify how frequently metrics should be exported. Defaults to 1 second.
61
+ pub metric_periodicity: Option<Duration>,
62
+ }
63
+
64
+ /// Configuration for the external export of traces
65
+ #[derive(Debug, Clone)]
66
+ pub struct TraceExportConfig {
67
+ /// An [EnvFilter](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html) filter string.
68
+ pub filter: String,
69
+ /// Where they should go
70
+ pub exporter: TraceExporter,
71
+ }
72
+
73
+ /// Control where traces are exported.
74
+ #[derive(Debug, Clone)]
75
+ pub enum TraceExporter {
76
+ /// Export traces to an OpenTelemetry Collector <https://opentelemetry.io/docs/collector/>.
77
+ Otel(OtelCollectorOptions),
78
+ }
79
+
80
+ /// Control where metrics are exported
81
+ #[derive(Debug, Clone)]
82
+ pub enum MetricsExporter {
83
+ /// Export metrics to an OpenTelemetry Collector <https://opentelemetry.io/docs/collector/>.
84
+ Otel(OtelCollectorOptions),
85
+ /// Expose metrics directly via an embedded http server bound to the provided address.
86
+ Prometheus(SocketAddr),
87
+ }
88
+
89
+ /// Control where logs go
90
+ #[derive(Debug, Clone)]
91
+ pub enum Logger {
92
+ /// Log directly to console.
93
+ Console {
94
+ /// An [EnvFilter](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html) filter string.
95
+ filter: String,
96
+ },
97
+ /// Forward logs to Lang - collectable with `fetch_global_buffered_logs`.
98
+ Forward {
99
+ /// An [EnvFilter](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html) filter string.
100
+ filter: String,
101
+ },
102
+ }
103
+
104
+ /// Types of aggregation temporality for metric export.
105
+ /// See: <https://github.com/open-telemetry/opentelemetry-specification/blob/ce50e4634efcba8da445cc23523243cb893905cb/specification/metrics/datamodel.md#temporality>
106
+ #[derive(Debug, Clone, Copy)]
107
+ pub enum MetricTemporality {
108
+ /// Successive data points repeat the starting timestamp
109
+ Cumulative,
110
+ /// Successive data points advance the starting timestamp
111
+ Delta,
112
+ }
113
+
114
+ impl Default for TelemetryOptions {
115
+ fn default() -> Self {
116
+ TelemetryOptionsBuilder::default().build().unwrap()
117
+ }
118
+ }
119
+
120
+ /// A log line (which ultimately came from a tracing event) exported from Core->Lang
121
+ #[derive(Debug)]
122
+ pub struct CoreLog {
123
+ /// The module within core this message originated from
124
+ pub target: String,
125
+ /// Log message
126
+ pub message: String,
127
+ /// Time log was generated (not when it was exported to lang)
128
+ pub timestamp: SystemTime,
129
+ /// Message level
130
+ pub level: Level,
131
+ /// Arbitrary k/v pairs (span k/vs are collapsed with event k/vs here). We could change this
132
+ /// to include them in `span_contexts` instead, but there's probably not much value for log
133
+ /// forwarding.
134
+ pub fields: HashMap<String, serde_json::Value>,
135
+ /// A list of the outermost to the innermost span names
136
+ pub span_contexts: Vec<String>,
137
+ }
138
+
139
+ impl CoreLog {
140
+ /// Return timestamp as ms since epoch
141
+ pub fn millis_since_epoch(&self) -> u128 {
142
+ self.timestamp
143
+ .duration_since(UNIX_EPOCH)
144
+ .unwrap_or(Duration::ZERO)
145
+ .as_millis()
146
+ }
147
+ }