temporalio 0.0.1 → 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.
Files changed (310) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +180 -7
  3. data/bridge/Cargo.lock +208 -76
  4. data/bridge/Cargo.toml +5 -2
  5. data/bridge/sdk-core/Cargo.toml +1 -1
  6. data/bridge/sdk-core/README.md +20 -10
  7. data/bridge/sdk-core/client/Cargo.toml +1 -1
  8. data/bridge/sdk-core/client/src/lib.rs +227 -59
  9. data/bridge/sdk-core/client/src/metrics.rs +17 -8
  10. data/bridge/sdk-core/client/src/raw.rs +13 -12
  11. data/bridge/sdk-core/client/src/retry.rs +132 -43
  12. data/bridge/sdk-core/core/Cargo.toml +28 -15
  13. data/bridge/sdk-core/core/benches/workflow_replay.rs +13 -10
  14. data/bridge/sdk-core/core/src/abstractions.rs +225 -36
  15. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +217 -79
  16. data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
  17. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +565 -34
  18. data/bridge/sdk-core/core/src/core_tests/queries.rs +247 -90
  19. data/bridge/sdk-core/core/src/core_tests/workers.rs +3 -5
  20. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
  21. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +430 -67
  22. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
  23. data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
  24. data/bridge/sdk-core/core/src/lib.rs +148 -34
  25. data/bridge/sdk-core/core/src/protosext/mod.rs +1 -1
  26. data/bridge/sdk-core/core/src/replay/mod.rs +185 -41
  27. data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
  28. data/bridge/sdk-core/core/src/telemetry/metrics.rs +219 -140
  29. data/bridge/sdk-core/core/src/telemetry/mod.rs +326 -315
  30. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +20 -14
  31. data/bridge/sdk-core/core/src/test_help/mod.rs +85 -21
  32. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
  33. data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
  34. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +364 -128
  35. data/bridge/sdk-core/core/src/worker/activities.rs +263 -170
  36. data/bridge/sdk-core/core/src/worker/client/mocks.rs +23 -3
  37. data/bridge/sdk-core/core/src/worker/client.rs +48 -6
  38. data/bridge/sdk-core/core/src/worker/mod.rs +186 -75
  39. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  40. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +13 -24
  41. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +879 -226
  42. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +101 -48
  43. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +8 -12
  44. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +6 -9
  45. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +90 -32
  46. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +6 -9
  47. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -10
  48. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +6 -9
  49. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +160 -83
  50. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +36 -54
  51. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +179 -0
  52. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +104 -157
  53. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +8 -12
  54. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -13
  55. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +10 -4
  56. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -11
  57. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
  58. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +395 -299
  59. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +12 -20
  60. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +33 -18
  61. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1032 -374
  62. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +525 -392
  63. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
  64. data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
  65. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +3 -6
  66. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
  67. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  68. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +456 -681
  69. data/bridge/sdk-core/core-api/Cargo.toml +6 -4
  70. data/bridge/sdk-core/core-api/src/errors.rs +1 -34
  71. data/bridge/sdk-core/core-api/src/lib.rs +7 -45
  72. data/bridge/sdk-core/core-api/src/telemetry.rs +141 -0
  73. data/bridge/sdk-core/core-api/src/worker.rs +27 -1
  74. data/bridge/sdk-core/etc/deps.svg +115 -140
  75. data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
  76. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
  77. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  78. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
  79. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  80. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  81. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  82. data/bridge/sdk-core/protos/api_upstream/buf.yaml +0 -3
  83. data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
  84. data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
  85. data/bridge/sdk-core/protos/api_upstream/{temporal/api/enums/v1/cluster.proto → build/tools.go} +7 -18
  86. data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
  87. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +12 -9
  88. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +15 -26
  89. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
  90. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  91. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +4 -9
  92. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  93. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +10 -8
  94. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +28 -2
  95. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  96. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  97. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  98. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  99. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  100. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
  101. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  102. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  103. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  104. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  105. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +62 -26
  106. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
  107. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +24 -61
  108. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -21
  109. data/bridge/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
  110. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  111. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  112. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +110 -31
  113. data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
  114. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +4 -4
  115. data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
  116. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  117. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +3 -2
  118. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +111 -36
  119. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +19 -5
  120. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
  121. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
  122. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
  123. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
  124. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
  125. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
  126. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +9 -0
  127. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +9 -1
  128. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
  129. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  130. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  131. data/bridge/sdk-core/sdk/Cargo.toml +4 -3
  132. data/bridge/sdk-core/sdk/src/interceptors.rs +36 -3
  133. data/bridge/sdk-core/sdk/src/lib.rs +94 -25
  134. data/bridge/sdk-core/sdk/src/workflow_context.rs +13 -2
  135. data/bridge/sdk-core/sdk/src/workflow_future.rs +10 -13
  136. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  137. data/bridge/sdk-core/sdk-core-protos/build.rs +36 -2
  138. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +164 -104
  139. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +27 -23
  140. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +252 -74
  141. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  142. data/bridge/sdk-core/test-utils/Cargo.toml +4 -1
  143. data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
  144. data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
  145. data/bridge/sdk-core/test-utils/src/lib.rs +161 -50
  146. data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  147. data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
  148. data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
  149. data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
  150. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
  151. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
  152. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +239 -0
  153. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -60
  154. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
  155. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
  156. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
  157. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
  158. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
  159. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
  160. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
  161. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
  162. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +151 -116
  163. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +54 -0
  164. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
  165. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +115 -24
  166. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
  167. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
  168. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
  169. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
  170. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
  171. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +27 -18
  172. data/bridge/sdk-core/tests/main.rs +8 -16
  173. data/bridge/sdk-core/tests/runner.rs +75 -36
  174. data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
  175. data/bridge/src/connection.rs +117 -82
  176. data/bridge/src/lib.rs +356 -42
  177. data/bridge/src/runtime.rs +10 -3
  178. data/bridge/src/test_server.rs +153 -0
  179. data/bridge/src/worker.rs +133 -9
  180. data/lib/gen/temporal/api/batch/v1/message_pb.rb +8 -6
  181. data/lib/gen/temporal/api/command/v1/message_pb.rb +10 -16
  182. data/lib/gen/temporal/api/common/v1/message_pb.rb +5 -1
  183. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +2 -1
  184. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +3 -3
  185. data/lib/gen/temporal/api/enums/v1/common_pb.rb +2 -1
  186. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +5 -4
  187. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +9 -1
  188. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +1 -1
  189. data/lib/gen/temporal/api/enums/v1/query_pb.rb +1 -1
  190. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +1 -1
  191. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +1 -1
  192. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +1 -1
  193. data/lib/gen/temporal/api/enums/v1/update_pb.rb +7 -10
  194. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +1 -1
  195. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +1 -1
  196. data/lib/gen/temporal/api/failure/v1/message_pb.rb +1 -1
  197. data/lib/gen/temporal/api/filter/v1/message_pb.rb +1 -1
  198. data/lib/gen/temporal/api/history/v1/message_pb.rb +34 -25
  199. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +2 -1
  200. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +14 -51
  201. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +1 -1
  202. data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
  203. data/lib/gen/temporal/api/query/v1/message_pb.rb +1 -1
  204. data/lib/gen/temporal/api/replication/v1/message_pb.rb +1 -1
  205. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +22 -1
  206. data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
  207. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +2 -2
  208. data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
  209. data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
  210. data/lib/gen/temporal/api/update/v1/message_pb.rb +49 -3
  211. data/lib/gen/temporal/api/version/v1/message_pb.rb +1 -1
  212. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +2 -1
  213. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +47 -20
  214. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +1 -1
  215. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
  216. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
  217. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
  218. data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
  219. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
  220. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
  221. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +28 -21
  222. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +32 -24
  223. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
  224. data/lib/temporalio/activity/context.rb +102 -0
  225. data/lib/temporalio/activity/info.rb +67 -0
  226. data/lib/temporalio/activity.rb +85 -0
  227. data/lib/temporalio/bridge/connect_options.rb +15 -0
  228. data/lib/temporalio/bridge/error.rb +8 -0
  229. data/lib/temporalio/bridge/retry_config.rb +24 -0
  230. data/lib/temporalio/bridge/tls_options.rb +19 -0
  231. data/lib/temporalio/bridge.rb +14 -0
  232. data/lib/{temporal → temporalio}/client/implementation.rb +57 -56
  233. data/lib/{temporal → temporalio}/client/workflow_handle.rb +35 -35
  234. data/lib/{temporal → temporalio}/client.rb +19 -32
  235. data/lib/temporalio/connection/retry_config.rb +44 -0
  236. data/lib/temporalio/connection/service.rb +20 -0
  237. data/lib/temporalio/connection/test_service.rb +92 -0
  238. data/lib/temporalio/connection/tls_options.rb +51 -0
  239. data/lib/temporalio/connection/workflow_service.rb +731 -0
  240. data/lib/temporalio/connection.rb +86 -0
  241. data/lib/{temporal → temporalio}/data_converter.rb +76 -35
  242. data/lib/{temporal → temporalio}/error/failure.rb +6 -6
  243. data/lib/{temporal → temporalio}/error/workflow_failure.rb +4 -2
  244. data/lib/{temporal → temporalio}/errors.rb +19 -1
  245. data/lib/{temporal → temporalio}/failure_converter/base.rb +5 -5
  246. data/lib/{temporal → temporalio}/failure_converter/basic.rb +58 -52
  247. data/lib/temporalio/failure_converter.rb +7 -0
  248. data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
  249. data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
  250. data/lib/{temporal → temporalio}/interceptor/chain.rb +7 -6
  251. data/lib/{temporal → temporalio}/interceptor/client.rb +27 -2
  252. data/lib/temporalio/interceptor.rb +22 -0
  253. data/lib/{temporal → temporalio}/payload_codec/base.rb +5 -5
  254. data/lib/{temporal → temporalio}/payload_converter/base.rb +3 -3
  255. data/lib/{temporal → temporalio}/payload_converter/bytes.rb +4 -3
  256. data/lib/{temporal → temporalio}/payload_converter/composite.rb +7 -5
  257. data/lib/{temporal → temporalio}/payload_converter/encoding_base.rb +4 -4
  258. data/lib/{temporal → temporalio}/payload_converter/json.rb +4 -3
  259. data/lib/{temporal → temporalio}/payload_converter/nil.rb +4 -3
  260. data/lib/temporalio/payload_converter.rb +14 -0
  261. data/lib/{temporal → temporalio}/retry_policy.rb +17 -7
  262. data/lib/{temporal → temporalio}/retry_state.rb +1 -1
  263. data/lib/temporalio/runtime.rb +25 -0
  264. data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
  265. data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
  266. data/lib/temporalio/testing/workflow_environment.rb +112 -0
  267. data/lib/temporalio/testing.rb +175 -0
  268. data/lib/{temporal → temporalio}/timeout_type.rb +2 -2
  269. data/lib/temporalio/version.rb +3 -0
  270. data/lib/temporalio/worker/activity_runner.rb +114 -0
  271. data/lib/temporalio/worker/activity_worker.rb +164 -0
  272. data/lib/temporalio/worker/reactor.rb +46 -0
  273. data/lib/temporalio/worker/runner.rb +63 -0
  274. data/lib/temporalio/worker/sync_worker.rb +124 -0
  275. data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
  276. data/lib/temporalio/worker.rb +204 -0
  277. data/lib/temporalio/workflow/async.rb +46 -0
  278. data/lib/{temporal → temporalio}/workflow/execution_info.rb +4 -4
  279. data/lib/{temporal → temporalio}/workflow/execution_status.rb +1 -1
  280. data/lib/temporalio/workflow/future.rb +138 -0
  281. data/lib/{temporal → temporalio}/workflow/id_reuse_policy.rb +6 -6
  282. data/lib/temporalio/workflow/info.rb +76 -0
  283. data/lib/{temporal → temporalio}/workflow/query_reject_condition.rb +5 -5
  284. data/lib/temporalio.rb +12 -3
  285. data/temporalio.gemspec +11 -6
  286. metadata +137 -64
  287. data/bridge/sdk-core/Cargo.lock +0 -2606
  288. data/bridge/sdk-core/bridge-ffi/Cargo.toml +0 -24
  289. data/bridge/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  290. data/bridge/sdk-core/bridge-ffi/build.rs +0 -25
  291. data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -249
  292. data/bridge/sdk-core/bridge-ffi/src/lib.rs +0 -825
  293. data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +0 -211
  294. data/bridge/sdk-core/core/src/log_export.rs +0 -62
  295. data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
  296. data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
  297. data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
  298. data/bridge/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  299. data/bridge/sdk-core/sdk/src/conversions.rs +0 -8
  300. data/lib/bridge.so +0 -0
  301. data/lib/gen/temporal/api/cluster/v1/message_pb.rb +0 -67
  302. data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +0 -26
  303. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
  304. data/lib/temporal/bridge.rb +0 -14
  305. data/lib/temporal/connection.rb +0 -736
  306. data/lib/temporal/failure_converter.rb +0 -8
  307. data/lib/temporal/payload_converter.rb +0 -14
  308. data/lib/temporal/runtime.rb +0 -22
  309. data/lib/temporal/version.rb +0 -3
  310. data/lib/temporal.rb +0 -8
@@ -1,17 +1,20 @@
1
+ //! This module helps with the initialization and management of telemetry. IE: Metrics and tracing.
2
+ //! Logs from core are all traces, which may be exported to the console, in memory, or externally.
3
+
4
+ mod log_export;
1
5
  pub(crate) mod metrics;
2
6
  mod prometheus_server;
3
7
 
4
- use crate::{
5
- log_export::CoreExportLogger,
6
- telemetry::{metrics::SDKAggSelector, prometheus_server::PromServer},
7
- CoreLog, METRIC_METER,
8
+ use crate::telemetry::{
9
+ log_export::{CoreLogExportLayer, CoreLogsOut},
10
+ metrics::SDKAggSelector,
11
+ prometheus_server::PromServer,
8
12
  };
13
+ use crossbeam::channel::Receiver;
9
14
  use itertools::Itertools;
10
- use log::LevelFilter;
11
15
  use once_cell::sync::OnceCell;
12
16
  use opentelemetry::{
13
- global,
14
- metrics::Meter,
17
+ metrics::{Meter, MeterProvider},
15
18
  runtime,
16
19
  sdk::{
17
20
  export::metrics::aggregation::{self, Temporality, TemporalitySelector},
@@ -21,369 +24,377 @@ use opentelemetry::{
21
24
  KeyValue,
22
25
  };
23
26
  use opentelemetry_otlp::WithExportConfig;
24
- use parking_lot::{const_mutex, Mutex};
27
+ use parking_lot::Mutex;
25
28
  use std::{
26
- collections::{HashMap, VecDeque},
29
+ cell::RefCell,
30
+ collections::VecDeque,
27
31
  convert::TryInto,
32
+ env,
28
33
  net::SocketAddr,
34
+ sync::{
35
+ atomic::{AtomicBool, Ordering},
36
+ Arc,
37
+ },
29
38
  time::Duration,
30
39
  };
31
- use temporal_sdk_core_api::CoreTelemetry;
40
+ use temporal_sdk_core_api::telemetry::{
41
+ CoreLog, CoreTelemetry, Logger, MetricTemporality, MetricsExporter, OtelCollectorOptions,
42
+ TelemetryOptions, TraceExporter,
43
+ };
32
44
  use tonic::metadata::MetadataMap;
33
- use tracing_subscriber::{filter::ParseError, layer::SubscriberExt, EnvFilter};
34
- use url::Url;
45
+ use tracing::{Level, Subscriber};
46
+ use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Layer};
35
47
 
36
48
  const TELEM_SERVICE_NAME: &str = "temporal-core-sdk";
37
- static DEFAULT_FILTER: &str = "temporal_sdk_core=INFO";
38
- static GLOBAL_TELEM_DAT: OnceCell<GlobalTelemDat> = OnceCell::new();
39
- static TELETM_MUTEX: Mutex<()> = const_mutex(());
40
-
41
- fn default_resource_kvs() -> &'static [KeyValue] {
42
- static INSTANCE: OnceCell<[KeyValue; 1]> = OnceCell::new();
43
- INSTANCE.get_or_init(|| [KeyValue::new("service.name", TELEM_SERVICE_NAME)])
44
- }
45
- fn default_resource() -> Resource {
46
- Resource::new(default_resource_kvs().iter().cloned())
47
- }
48
-
49
- /// Options for exporting to an OpenTelemetry Collector
50
- #[derive(Debug, Clone)]
51
- pub struct OtelCollectorOptions {
52
- /// The url of the OTel collector to export telemetry and metrics to. Lang SDK should also
53
- /// export to this same collector.
54
- pub url: Url,
55
- /// Optional set of HTTP headers to send to the Collector, e.g for authentication.
56
- pub headers: HashMap<String, String>,
57
- }
58
-
59
- /// Control where traces are exported
60
- #[derive(Debug, Clone)]
61
- pub enum TraceExporter {
62
- /// Export traces to an OpenTelemetry Collector <https://opentelemetry.io/docs/collector/>.
63
- Otel(OtelCollectorOptions),
64
- }
65
49
 
66
- /// Control where metrics are exported
67
- #[derive(Debug, Clone)]
68
- pub enum MetricsExporter {
69
- /// Export metrics to an OpenTelemetry Collector <https://opentelemetry.io/docs/collector/>.
70
- Otel(OtelCollectorOptions),
71
- /// Expose metrics directly via an embedded http server bound to the provided address.
72
- Prometheus(SocketAddr),
50
+ /// Help you construct an [EnvFilter] compatible filter string which will forward all core module
51
+ /// traces at `core_level` and all others (from 3rd party modules, etc) at `other_level`.
52
+ pub fn construct_filter_string(core_level: Level, other_level: Level) -> String {
53
+ format!(
54
+ "{other_level},temporal_sdk_core={core_level},temporal_client={core_level},temporal_sdk={core_level}"
55
+ )
73
56
  }
74
57
 
75
- /// Control where logs go
76
- #[derive(Debug, Clone, Copy)]
77
- pub enum Logger {
78
- /// Log directly to console.
79
- Console,
80
- /// Forward logs to Lang - collectable with `fetch_global_buffered_logs`.
81
- Forward(LevelFilter),
58
+ /// Holds initialized tracing/metrics exporters, etc
59
+ pub struct TelemetryInstance {
60
+ metric_prefix: &'static str,
61
+ logs_out: Option<Mutex<CoreLogsOut>>,
62
+ metrics: Option<(Box<dyn MeterProvider + Send + Sync + 'static>, Meter)>,
63
+ trace_subscriber: Arc<dyn Subscriber + Send + Sync>,
64
+ prom_binding: Option<SocketAddr>,
65
+ _keepalive_rx: Receiver<()>,
82
66
  }
83
67
 
84
- /// Telemetry configuration options. Construct with [TelemetryOptionsBuilder]
85
- #[derive(Debug, Clone, derive_builder::Builder)]
86
- #[non_exhaustive]
87
- pub struct TelemetryOptions {
88
- /// A string in the [EnvFilter] format which specifies what tracing data is included in
89
- /// telemetry, log forwarded to lang, or console output. May be overridden by the
90
- /// `TEMPORAL_TRACING_FILTER` env variable.
91
- #[builder(default = "DEFAULT_FILTER.to_string()")]
92
- pub tracing_filter: String,
93
-
94
- /// Optional trace exporter - set as None to disable.
95
- #[builder(setter(into, strip_option), default)]
96
- pub tracing: Option<TraceExporter>,
97
- /// Optional logger - set as None to disable.
98
- #[builder(setter(into, strip_option), default)]
99
- pub logging: Option<Logger>,
100
- /// Optional metrics exporter - set as None to disable.
101
- #[builder(setter(into, strip_option), default)]
102
- pub metrics: Option<MetricsExporter>,
103
-
104
- /// If set true, do not prefix metrics with `temporal_`. Will be removed eventually as
105
- /// the prefix is consistent with other SDKs.
106
- #[builder(default)]
107
- pub no_temporal_prefix_for_metrics: bool,
108
-
109
- /// Specifies the aggregation temporality for metric export. Defaults to cumulative.
110
- #[builder(default = "MetricTemporality::Cumulative")]
111
- pub metric_temporality: MetricTemporality,
112
- }
68
+ impl TelemetryInstance {
69
+ fn new(
70
+ trace_subscriber: Arc<dyn Subscriber + Send + Sync>,
71
+ logs_out: Option<Mutex<CoreLogsOut>>,
72
+ metric_prefix: &'static str,
73
+ mut meter_provider: Option<Box<dyn MeterProvider + Send + Sync + 'static>>,
74
+ prom_binding: Option<SocketAddr>,
75
+ keepalive_rx: Receiver<()>,
76
+ ) -> Self {
77
+ let metrics = meter_provider.take().map(|mp| {
78
+ let meter = mp.meter(TELEM_SERVICE_NAME);
79
+ (mp, meter)
80
+ });
81
+ Self {
82
+ metric_prefix,
83
+ logs_out,
84
+ metrics,
85
+ trace_subscriber,
86
+ prom_binding,
87
+ _keepalive_rx: keepalive_rx,
88
+ }
89
+ }
113
90
 
114
- /// Types of aggregation temporality for metric export.
115
- /// See: <https://github.com/open-telemetry/opentelemetry-specification/blob/ce50e4634efcba8da445cc23523243cb893905cb/specification/metrics/datamodel.md#temporality>
116
- #[derive(Debug, Clone, Copy)]
117
- pub enum MetricTemporality {
118
- /// Successive data points repeat the starting timestamp
119
- Cumulative,
120
- /// Successive data points advance the starting timestamp
121
- Delta,
122
- }
91
+ /// Returns a trace subscriber which can be used with the tracing crate, or with our own
92
+ /// [set_trace_subscriber_for_current_thread] function.
93
+ pub fn trace_subscriber(&self) -> Arc<dyn Subscriber + Send + Sync> {
94
+ self.trace_subscriber.clone()
95
+ }
123
96
 
124
- impl MetricTemporality {
125
- fn to_selector(self) -> impl TemporalitySelector + Send + Sync + Clone {
126
- match self {
127
- MetricTemporality::Cumulative => {
128
- aggregation::constant_temporality_selector(Temporality::Cumulative)
129
- }
130
- MetricTemporality::Delta => {
131
- aggregation::constant_temporality_selector(Temporality::Delta)
132
- }
133
- }
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
134
100
  }
135
- }
136
101
 
137
- impl TelemetryOptions {
138
- /// Construct an [EnvFilter] from given `tracing_filter`.
139
- pub fn try_get_env_filter(&self) -> Result<EnvFilter, ParseError> {
140
- EnvFilter::try_new(if self.tracing_filter.is_empty() {
141
- DEFAULT_FILTER
142
- } else {
143
- &self.tracing_filter
144
- })
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))
145
107
  }
146
108
  }
147
109
 
148
- impl Default for TelemetryOptions {
149
- fn default() -> Self {
150
- TelemetryOptionsBuilder::default().build().unwrap()
151
- }
110
+ thread_local! {
111
+ static SUB_GUARD: RefCell<Option<tracing::subscriber::DefaultGuard>> = RefCell::new(None);
112
+ }
113
+ /// Set the trace subscriber for the current thread. This must be done in every thread which uses
114
+ /// core stuff, otherwise traces/logs will not be collected on that thread. For example, if using
115
+ /// a multithreaded Tokio runtime, you should ensure that said runtime uses
116
+ /// [on_thread_start](https://docs.rs/tokio/latest/tokio/runtime/struct.Builder.html#method.on_thread_start)
117
+ /// or a similar mechanism to call this for each thread within the runtime.
118
+ pub fn set_trace_subscriber_for_current_thread(sub: impl Subscriber + Send + Sync + 'static) {
119
+ SUB_GUARD.with(|sg| {
120
+ if sg.borrow().is_none() {
121
+ let g = tracing::subscriber::set_default(sub);
122
+ *sg.borrow_mut() = Some(g);
123
+ }
124
+ })
152
125
  }
153
126
 
154
- /// Things that need to not be dropped while telemetry is ongoing
155
- #[derive(Default)]
156
- pub struct GlobalTelemDat {
157
- core_export_logger: Option<CoreExportLogger>,
158
- runtime: Option<tokio::runtime::Runtime>,
159
- prom_srv: Option<PromServer>,
160
- no_temporal_prefix_for_metrics: bool,
127
+ /// Undoes [set_trace_subscriber_for_current_thread]
128
+ pub fn remove_trace_subscriber_for_current_thread() {
129
+ SUB_GUARD.with(|sg| sg.take());
161
130
  }
162
131
 
163
- impl GlobalTelemDat {
164
- fn init(&'static self) {
165
- if let Some(loggr) = &self.core_export_logger {
166
- let _ = log::set_logger(loggr);
167
- }
168
- if let Some(srv) = &self.prom_srv {
169
- self.runtime
170
- .as_ref()
171
- .expect("Telemetry runtime is initted")
172
- .spawn(srv.run());
173
- }
132
+ fn metric_prefix(opts: &TelemetryOptions) -> &'static str {
133
+ if opts.no_temporal_prefix_for_metrics {
134
+ ""
135
+ } else {
136
+ "temporal_"
174
137
  }
175
138
  }
176
139
 
177
- impl CoreTelemetry for GlobalTelemDat {
140
+ impl CoreTelemetry for TelemetryInstance {
178
141
  fn fetch_buffered_logs(&self) -> Vec<CoreLog> {
179
- fetch_global_buffered_logs()
180
- }
181
-
182
- fn get_metric_meter(&self) -> Option<&Meter> {
183
- if GLOBAL_TELEM_DAT.get().is_some() {
184
- return Some(&METRIC_METER);
142
+ if let Some(logs_out) = self.logs_out.as_ref() {
143
+ logs_out.lock().pop_iter().collect()
144
+ } else {
145
+ vec![]
185
146
  }
186
- None
187
147
  }
188
148
  }
189
149
 
190
- /// Initialize tracing subscribers/output and logging export. If this function is called more than
191
- /// once, subsequent calls do nothing.
150
+ /// Initialize tracing subscribers/output and logging export, returning a [TelemetryInstance]
151
+ /// which can be used to register default / global tracing subscribers.
152
+ ///
153
+ /// You should only call this once per unique [TelemetryOptions]
192
154
  ///
193
155
  /// See [TelemetryOptions] docs for more on configuration.
194
- pub fn telemetry_init(opts: &TelemetryOptions) -> Result<&'static GlobalTelemDat, anyhow::Error> {
195
- // TODO: Per-layer filtering has been implemented but does not yet support
196
- // env-filter. When it does, allow filtering logs/telemetry separately.
197
-
198
- // Ensure we don't pointlessly spawn threads that won't do anything or call telem dat's init 2x
199
- let guard = TELETM_MUTEX.lock();
200
- if let Some(gtd) = GLOBAL_TELEM_DAT.get() {
201
- return Ok(gtd);
202
- }
203
-
156
+ pub fn telemetry_init(opts: TelemetryOptions) -> Result<TelemetryInstance, anyhow::Error> {
204
157
  // This is a bit odd, but functional. It's desirable to create a separate tokio runtime for
205
158
  // metrics handling, since tests typically use a single-threaded runtime and initializing
206
159
  // pipeline requires us to know if the runtime is single or multithreaded, we will crash
207
160
  // in one case or the other. There does not seem to be a way to tell from the current runtime
208
161
  // handle if it is single or multithreaded. Additionally, we can isolate metrics work this
209
162
  // way which is nice.
210
- let opts = opts.clone();
211
- std::thread::spawn(move || {
212
- let res = GLOBAL_TELEM_DAT.get_or_try_init::<_, anyhow::Error>(move || {
213
- // Ensure closure captures the mutex guard
214
- let _ = &*guard;
215
-
216
- let runtime = tokio::runtime::Builder::new_multi_thread()
217
- .thread_name("telemetry")
218
- .worker_threads(2)
219
- .enable_all()
220
- .build()?;
221
- let mut globaldat = GlobalTelemDat {
222
- no_temporal_prefix_for_metrics: opts.no_temporal_prefix_for_metrics,
223
- ..Default::default()
224
- };
225
-
226
- if let Some(ref logger) = opts.logging {
227
- match logger {
228
- Logger::Console => {
229
- // TODO: this is duplicated below and is quite ugly, remove the duplication
230
- if opts.tracing.is_none() {
231
- let pretty_fmt = tracing_subscriber::fmt::format()
232
- .pretty()
233
- .with_source_location(false);
234
- let reg = tracing_subscriber::registry()
235
- .with((opts).try_get_env_filter()?)
236
- .with(
237
- tracing_subscriber::fmt::layer()
238
- .with_target(false)
239
- .event_format(pretty_fmt),
240
- );
241
- tracing::subscriber::set_global_default(reg)?;
242
- }
243
- }
244
- Logger::Forward(filter) => {
245
- log::set_max_level(*filter);
246
- globaldat.core_export_logger = Some(CoreExportLogger::new(*filter));
247
- }
248
- };
249
- };
250
-
251
- if let Some(ref metrics) = opts.metrics {
252
- match metrics {
253
- MetricsExporter::Prometheus(addr) => {
254
- let srv = PromServer::new(*addr, opts.metric_temporality.to_selector())?;
255
- globaldat.prom_srv = Some(srv);
256
- }
257
- MetricsExporter::Otel(OtelCollectorOptions { url, headers }) => {
258
- runtime.block_on(async {
259
- let metrics = opentelemetry_otlp::new_pipeline()
260
- .metrics(
261
- SDKAggSelector,
262
- opts.metric_temporality.to_selector(),
263
- runtime::Tokio,
163
+ let (tx, rx) = crossbeam::channel::bounded(0);
164
+ let (keepalive_tx, keepalive_rx) = crossbeam::channel::bounded(0);
165
+ let jh = std::thread::spawn(move || -> Result<(), anyhow::Error> {
166
+ let runtime = tokio::runtime::Builder::new_multi_thread()
167
+ .thread_name("telemetry")
168
+ .worker_threads(2)
169
+ .enable_all()
170
+ .build()?;
171
+ // Parts of telem dat ====
172
+ let mut logs_out = None;
173
+ let metric_prefix = metric_prefix(&opts);
174
+ let mut prom_binding = None;
175
+ // =======================
176
+
177
+ // Tracing subscriber layers =========
178
+ let mut console_pretty_layer = None;
179
+ let mut console_compact_layer = None;
180
+ let mut forward_layer = None;
181
+ let mut export_layer = None;
182
+ // ===================================
183
+
184
+ if let Some(ref logger) = opts.logging {
185
+ match logger {
186
+ Logger::Console { filter } => {
187
+ // This is silly dupe but can't be avoided without boxing.
188
+ if env::var("TEMPORAL_CORE_PRETTY_LOGS").is_ok() {
189
+ console_pretty_layer = Some(
190
+ tracing_subscriber::fmt::layer()
191
+ .with_target(false)
192
+ .event_format(
193
+ tracing_subscriber::fmt::format()
194
+ .pretty()
195
+ .with_source_location(false),
264
196
  )
265
- .with_period(Duration::from_secs(1))
266
- .with_resource(default_resource())
267
- .with_exporter(
268
- // No joke exporter builder literally not cloneable for some insane
269
- // reason
270
- opentelemetry_otlp::new_exporter()
271
- .tonic()
272
- .with_endpoint(url.to_string())
273
- .with_metadata(MetadataMap::from_headers(
274
- headers.try_into()?,
275
- )),
197
+ .with_filter(EnvFilter::new(filter)),
198
+ )
199
+ } else {
200
+ console_compact_layer = Some(
201
+ tracing_subscriber::fmt::layer()
202
+ .with_target(false)
203
+ .event_format(
204
+ tracing_subscriber::fmt::format()
205
+ .compact()
206
+ .with_source_location(false),
276
207
  )
277
- .build()?;
278
- global::set_meter_provider(metrics);
279
- Result::<(), anyhow::Error>::Ok(())
280
- })?;
208
+ .with_filter(EnvFilter::new(filter)),
209
+ )
281
210
  }
282
- };
211
+ }
212
+ Logger::Forward { filter } => {
213
+ let (export_layer, lo) = CoreLogExportLayer::new();
214
+ logs_out = Some(Mutex::new(lo));
215
+ forward_layer = Some(export_layer.with_filter(EnvFilter::new(filter)));
216
+ }
283
217
  };
284
-
285
- if let Some(ref tracing) = opts.tracing {
286
- match tracing {
287
- TraceExporter::Otel(OtelCollectorOptions { url, headers }) => {
288
- runtime.block_on(async {
289
- let tracer_cfg = Config::default().with_resource(default_resource());
290
- let tracer = opentelemetry_otlp::new_pipeline()
291
- .tracing()
292
- .with_exporter(
293
- opentelemetry_otlp::new_exporter()
294
- .tonic()
295
- .with_endpoint(url.to_string())
296
- .with_metadata(MetadataMap::from_headers(
297
- headers.try_into()?,
298
- )),
299
- )
300
- .with_trace_config(tracer_cfg)
301
- .install_batch(runtime::Tokio)?;
302
-
303
- let opentelemetry = tracing_opentelemetry::layer().with_tracer(tracer);
304
-
305
- // TODO: remove all of this duplicate code
306
- if let Some(Logger::Console) = opts.logging {
307
- let pretty_fmt = tracing_subscriber::fmt::format()
308
- .pretty()
309
- .with_source_location(false);
310
- let reg = tracing_subscriber::registry()
311
- .with(opentelemetry)
312
- .with(opts.try_get_env_filter()?)
313
- .with(
314
- tracing_subscriber::fmt::layer()
315
- .with_target(false)
316
- .event_format(pretty_fmt),
317
- );
318
- // Can't use try_init here as it will blow away our custom logger if we do
319
- tracing::subscriber::set_global_default(reg)?;
320
- } else {
321
- let reg = tracing_subscriber::registry()
322
- .with(opentelemetry)
323
- .with(opts.try_get_env_filter()?);
324
- // Can't use try_init here as it will blow away our custom logger if we do
325
- tracing::subscriber::set_global_default(reg)?;
326
- }
327
- Result::<(), anyhow::Error>::Ok(())
328
- })?;
329
- }
330
- };
218
+ };
219
+
220
+ let meter_provider = if let Some(ref metrics) = opts.metrics {
221
+ let aggregator = SDKAggSelector { metric_prefix };
222
+ match metrics {
223
+ MetricsExporter::Prometheus(addr) => {
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());
232
+ let mp = srv.exporter.meter_provider()?;
233
+ runtime.spawn(async move { srv.run().await });
234
+ Some(Box::new(mp) as Box<dyn MeterProvider + Send + Sync>)
235
+ }
236
+ MetricsExporter::Otel(OtelCollectorOptions {
237
+ url,
238
+ headers,
239
+ metric_periodicity,
240
+ }) => runtime.block_on(async {
241
+ let metrics = opentelemetry_otlp::new_pipeline()
242
+ .metrics(
243
+ aggregator,
244
+ metric_temporality_to_selector(opts.metric_temporality),
245
+ runtime::Tokio,
246
+ )
247
+ .with_period(metric_periodicity.unwrap_or_else(|| Duration::from_secs(1)))
248
+ .with_resource(default_resource())
249
+ .with_exporter(
250
+ opentelemetry_otlp::new_exporter()
251
+ .tonic()
252
+ .with_endpoint(url.to_string())
253
+ .with_metadata(MetadataMap::from_headers(headers.try_into()?)),
254
+ )
255
+ .build()?;
256
+ Ok::<_, anyhow::Error>(Some(
257
+ Box::new(metrics) as Box<dyn MeterProvider + Send + Sync>
258
+ ))
259
+ })?,
260
+ }
261
+ } else {
262
+ None
263
+ };
264
+
265
+ if let Some(ref tracing) = opts.tracing {
266
+ match &tracing.exporter {
267
+ TraceExporter::Otel(OtelCollectorOptions { url, headers, .. }) => {
268
+ runtime.block_on(async {
269
+ let tracer_cfg = Config::default().with_resource(default_resource());
270
+ let tracer = opentelemetry_otlp::new_pipeline()
271
+ .tracing()
272
+ .with_exporter(
273
+ opentelemetry_otlp::new_exporter()
274
+ .tonic()
275
+ .with_endpoint(url.to_string())
276
+ .with_metadata(MetadataMap::from_headers(headers.try_into()?)),
277
+ )
278
+ .with_trace_config(tracer_cfg)
279
+ .install_batch(runtime::Tokio)?;
280
+
281
+ let opentelemetry = tracing_opentelemetry::layer()
282
+ .with_tracer(tracer)
283
+ .with_filter(EnvFilter::new(&tracing.filter));
284
+
285
+ export_layer = Some(opentelemetry);
286
+ Result::<(), anyhow::Error>::Ok(())
287
+ })?;
288
+ }
331
289
  };
332
-
333
- globaldat.runtime = Some(runtime);
334
- Ok(globaldat)
335
- })?;
336
-
337
- res.init();
338
- Result::<_, anyhow::Error>::Ok(res)
339
- })
340
- .join()
341
- .expect("Telemetry initialization panicked")
290
+ };
291
+
292
+ let reg = tracing_subscriber::registry()
293
+ .with(console_pretty_layer)
294
+ .with(console_compact_layer)
295
+ .with(forward_layer)
296
+ .with(export_layer);
297
+
298
+ tx.send(TelemetryInstance::new(
299
+ Arc::new(reg),
300
+ logs_out,
301
+ metric_prefix,
302
+ meter_provider,
303
+ prom_binding,
304
+ keepalive_rx,
305
+ ))
306
+ .expect("Must be able to send telem instance out of thread");
307
+ // Now keep the thread alive until the telemetry instance is dropped by trying to send
308
+ // something forever
309
+ let _ = keepalive_tx.send(());
310
+ Ok(())
311
+ });
312
+ match rx.recv() {
313
+ Ok(ti) => Ok(ti),
314
+ Err(_) => {
315
+ // Immediately join the thread since something went wrong in it
316
+ jh.join().expect("Telemetry must init cleanly")?;
317
+ // This can't happen. The rx channel can't be dropped unless the thread errored.
318
+ unreachable!("Impossible error in telemetry init thread");
319
+ }
320
+ }
342
321
  }
343
322
 
344
- /// Returned buffered logs for export to lang from the global logging instance.
345
- /// If [telemetry_init] has not been called, always returns an empty vec.
346
- pub fn fetch_global_buffered_logs() -> Vec<CoreLog> {
347
- if let Some(loggr) = GLOBAL_TELEM_DAT
348
- .get()
349
- .and_then(|gd| gd.core_export_logger.as_ref())
323
+ /// Initialize telemetry/tracing globally. Useful for testing. Only takes affect when called
324
+ /// the first time. Subsequent calls are ignored.
325
+ pub fn telemetry_init_global(opts: TelemetryOptions) -> Result<(), anyhow::Error> {
326
+ static INITTED: AtomicBool = AtomicBool::new(false);
327
+ if INITTED
328
+ .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
329
+ .is_ok()
350
330
  {
351
- loggr.drain()
352
- } else {
353
- vec![]
331
+ let ti = telemetry_init(opts)?;
332
+ tracing::subscriber::set_global_default(ti.trace_subscriber())?;
354
333
  }
334
+ Ok(())
355
335
  }
356
336
 
357
- #[allow(dead_code)] // Not always used, called to enable for debugging when needed
358
- #[cfg(test)]
359
- pub(crate) fn test_telem_console() {
360
- telemetry_init(&TelemetryOptions {
361
- tracing_filter: "temporal_sdk_core=DEBUG,temporal_sdk=DEBUG".to_string(),
362
- logging: Some(Logger::Console),
363
- tracing: None,
364
- metrics: None,
365
- no_temporal_prefix_for_metrics: false,
366
- metric_temporality: MetricTemporality::Cumulative,
367
- })
368
- .unwrap();
337
+ fn default_resource_kvs() -> &'static [KeyValue] {
338
+ static INSTANCE: OnceCell<[KeyValue; 1]> = OnceCell::new();
339
+ INSTANCE.get_or_init(|| [KeyValue::new("service.name", TELEM_SERVICE_NAME)])
340
+ }
341
+ fn default_resource() -> Resource {
342
+ Resource::new(default_resource_kvs().iter().cloned())
343
+ }
344
+
345
+ fn metric_temporality_to_selector(
346
+ t: MetricTemporality,
347
+ ) -> impl TemporalitySelector + Send + Sync + Clone {
348
+ match t {
349
+ MetricTemporality::Cumulative => {
350
+ aggregation::constant_temporality_selector(Temporality::Cumulative)
351
+ }
352
+ MetricTemporality::Delta => aggregation::constant_temporality_selector(Temporality::Delta),
353
+ }
369
354
  }
370
355
 
371
- #[allow(dead_code)] // Not always used, called to enable for debugging when needed
372
356
  #[cfg(test)]
373
- pub(crate) fn test_telem_collector() {
374
- telemetry_init(&TelemetryOptions {
375
- tracing_filter: "temporal_sdk_core=DEBUG,temporal_sdk=DEBUG".to_string(),
376
- logging: Some(Logger::Console),
377
- tracing: Some(TraceExporter::Otel(OtelCollectorOptions {
378
- url: "grpc://localhost:4317".parse().unwrap(),
379
- headers: Default::default(),
380
- })),
381
- metrics: None,
382
- no_temporal_prefix_for_metrics: false,
383
- metric_temporality: MetricTemporality::Cumulative,
384
- })
385
- .unwrap();
357
+ pub mod test_initters {
358
+ use super::*;
359
+ use temporal_sdk_core_api::telemetry::{TelemetryOptionsBuilder, TraceExportConfig};
360
+
361
+ #[allow(dead_code)] // Not always used, called to enable for debugging when needed
362
+ pub fn test_telem_console() {
363
+ telemetry_init_global(
364
+ TelemetryOptionsBuilder::default()
365
+ .logging(Logger::Console {
366
+ filter: construct_filter_string(Level::DEBUG, Level::WARN),
367
+ })
368
+ .build()
369
+ .unwrap(),
370
+ )
371
+ .unwrap();
372
+ }
373
+
374
+ #[allow(dead_code)] // Not always used, called to enable for debugging when needed
375
+ pub fn test_telem_collector() {
376
+ telemetry_init_global(
377
+ TelemetryOptionsBuilder::default()
378
+ .logging(Logger::Console {
379
+ filter: construct_filter_string(Level::DEBUG, Level::WARN),
380
+ })
381
+ .tracing(TraceExportConfig {
382
+ filter: construct_filter_string(Level::DEBUG, Level::WARN),
383
+ exporter: TraceExporter::Otel(OtelCollectorOptions {
384
+ url: "grpc://localhost:4317".parse().unwrap(),
385
+ headers: Default::default(),
386
+ metric_periodicity: None,
387
+ }),
388
+ })
389
+ .build()
390
+ .unwrap(),
391
+ )
392
+ .unwrap();
393
+ }
386
394
  }
395
+ use crate::telemetry::metrics::TemporalMeter;
396
+ #[cfg(test)]
397
+ pub use test_initters::*;
387
398
 
388
399
  /// A trait for using [Display] on the contents of vecs, etc, which don't implement it.
389
400
  ///