@temporalio/core-bridge 1.8.5 → 1.9.0-rc.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 (196) hide show
  1. package/Cargo.lock +189 -152
  2. package/Cargo.toml +1 -0
  3. package/lib/index.d.ts +17 -44
  4. package/lib/index.js.map +1 -1
  5. package/package.json +3 -4
  6. package/releases/aarch64-apple-darwin/index.node +0 -0
  7. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  8. package/releases/x86_64-apple-darwin/index.node +0 -0
  9. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  10. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  11. package/sdk-core/.github/workflows/heavy.yml +4 -0
  12. package/sdk-core/.github/workflows/per-pr.yml +96 -0
  13. package/sdk-core/ARCHITECTURE.md +1 -1
  14. package/sdk-core/Cargo.toml +6 -0
  15. package/sdk-core/README.md +37 -21
  16. package/sdk-core/client/Cargo.toml +6 -3
  17. package/sdk-core/client/src/lib.rs +272 -138
  18. package/sdk-core/client/src/metrics.rs +68 -57
  19. package/sdk-core/client/src/raw.rs +191 -45
  20. package/sdk-core/client/src/retry.rs +20 -0
  21. package/sdk-core/client/src/worker_registry/mod.rs +264 -0
  22. package/sdk-core/client/src/workflow_handle/mod.rs +2 -1
  23. package/sdk-core/core/Cargo.toml +16 -18
  24. package/sdk-core/core/src/core_tests/child_workflows.rs +7 -7
  25. package/sdk-core/core/src/core_tests/mod.rs +1 -0
  26. package/sdk-core/core/src/core_tests/replay_flag.rs +29 -39
  27. package/sdk-core/core/src/core_tests/updates.rs +73 -0
  28. package/sdk-core/core/src/core_tests/workflow_tasks.rs +52 -1
  29. package/sdk-core/core/src/ephemeral_server/mod.rs +34 -11
  30. package/sdk-core/core/src/internal_flags.rs +7 -1
  31. package/sdk-core/core/src/lib.rs +19 -36
  32. package/sdk-core/core/src/protosext/mod.rs +11 -3
  33. package/sdk-core/core/src/protosext/protocol_messages.rs +102 -0
  34. package/sdk-core/core/src/replay/mod.rs +100 -48
  35. package/sdk-core/core/src/telemetry/log_export.rs +161 -28
  36. package/sdk-core/core/src/telemetry/metrics.rs +869 -248
  37. package/sdk-core/core/src/telemetry/mod.rs +135 -239
  38. package/sdk-core/core/src/telemetry/prometheus_server.rs +36 -31
  39. package/sdk-core/core/src/test_help/mod.rs +63 -4
  40. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +12 -2
  41. package/sdk-core/core/src/worker/activities.rs +276 -10
  42. package/sdk-core/core/src/worker/client/mocks.rs +18 -0
  43. package/sdk-core/core/src/worker/client.rs +16 -3
  44. package/sdk-core/core/src/worker/mod.rs +50 -19
  45. package/sdk-core/core/src/worker/slot_provider.rs +175 -0
  46. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +27 -34
  47. package/sdk-core/core/src/worker/workflow/history_update.rs +4 -1
  48. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +36 -94
  49. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +34 -22
  50. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +50 -34
  51. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +106 -92
  52. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +22 -21
  53. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +386 -499
  54. package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -2
  55. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +33 -26
  56. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +198 -215
  57. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +66 -62
  58. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +88 -119
  59. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +3 -1
  60. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +411 -0
  61. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +26 -25
  62. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +302 -85
  63. package/sdk-core/core/src/worker/workflow/managed_run.rs +179 -132
  64. package/sdk-core/core/src/worker/workflow/mod.rs +121 -46
  65. package/sdk-core/core/src/worker/workflow/run_cache.rs +8 -12
  66. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +45 -38
  67. package/sdk-core/core-api/Cargo.toml +7 -6
  68. package/sdk-core/core-api/src/lib.rs +4 -12
  69. package/sdk-core/core-api/src/telemetry/metrics.rs +334 -0
  70. package/sdk-core/core-api/src/telemetry.rs +53 -42
  71. package/sdk-core/core-api/src/worker.rs +7 -0
  72. package/sdk-core/{.buildkite/docker → docker}/docker-compose.yaml +1 -1
  73. package/sdk-core/etc/dynamic-config.yaml +11 -1
  74. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
  75. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +1 -3
  76. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +2 -2
  77. package/sdk-core/sdk/Cargo.toml +1 -1
  78. package/sdk-core/sdk/src/lib.rs +85 -7
  79. package/sdk-core/sdk/src/workflow_context/options.rs +4 -0
  80. package/sdk-core/sdk/src/workflow_context.rs +43 -15
  81. package/sdk-core/sdk/src/workflow_future.rs +334 -204
  82. package/sdk-core/sdk-core-protos/Cargo.toml +2 -2
  83. package/sdk-core/sdk-core-protos/build.rs +14 -14
  84. package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/Dockerfile +2 -0
  85. package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +99 -0
  86. package/sdk-core/sdk-core-protos/protos/api_upstream/api-linter.yaml +56 -0
  87. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.gen.yaml +20 -0
  88. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.lock +11 -0
  89. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +18 -0
  90. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/annotations.proto +31 -0
  91. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/http.proto +379 -0
  92. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/any.proto +162 -0
  93. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/descriptor.proto +1212 -0
  94. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/duration.proto +115 -0
  95. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/empty.proto +51 -0
  96. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/timestamp.proto +144 -0
  97. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/wrappers.proto +123 -0
  98. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/batch/v1/message.proto +3 -5
  99. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/command/v1/message.proto +11 -13
  100. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/common/v1/message.proto +2 -4
  101. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  102. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/reset.proto +1 -1
  103. package/sdk-core/{protos/api_upstream/build/tools.go → sdk-core-protos/protos/api_upstream/temporal/api/export/v1/message.proto} +22 -6
  104. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/filter/v1/message.proto +2 -4
  105. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/history/v1/message.proto +21 -23
  106. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/namespace/v1/message.proto +2 -4
  107. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -0
  108. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -0
  109. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/replication/v1/message.proto +1 -3
  110. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/schedule/v1/message.proto +36 -20
  111. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +13 -0
  112. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -4
  113. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/update/v1/message.proto +1 -1
  114. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/version/v1/message.proto +2 -3
  115. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflow/v1/message.proto +18 -20
  116. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/request_response.proto +84 -32
  117. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/service.proto +205 -47
  118. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +57 -0
  119. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +27 -0
  120. package/sdk-core/sdk-core-protos/src/history_builder.rs +67 -2
  121. package/sdk-core/sdk-core-protos/src/lib.rs +75 -2
  122. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  123. package/sdk-core/test-utils/Cargo.toml +5 -1
  124. package/sdk-core/test-utils/src/canned_histories.rs +3 -57
  125. package/sdk-core/test-utils/src/interceptors.rs +46 -0
  126. package/sdk-core/test-utils/src/lib.rs +106 -38
  127. package/sdk-core/tests/integ_tests/metrics_tests.rs +110 -15
  128. package/sdk-core/tests/integ_tests/queries_tests.rs +174 -3
  129. package/sdk-core/tests/integ_tests/update_tests.rs +908 -0
  130. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +44 -1
  131. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -1
  132. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  133. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -4
  134. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +61 -0
  135. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +27 -2
  136. package/sdk-core/tests/integ_tests/workflow_tests.rs +1 -0
  137. package/sdk-core/tests/main.rs +2 -1
  138. package/sdk-core/tests/runner.rs +15 -2
  139. package/src/conversions.rs +75 -89
  140. package/src/helpers.rs +74 -0
  141. package/src/runtime.rs +17 -6
  142. package/src/worker.rs +14 -61
  143. package/ts/index.ts +21 -52
  144. package/sdk-core/.buildkite/docker/Dockerfile +0 -9
  145. package/sdk-core/.buildkite/docker/build.sh +0 -5
  146. package/sdk-core/.buildkite/docker/docker-compose-ci.yaml +0 -27
  147. package/sdk-core/.buildkite/pipeline.yml +0 -57
  148. package/sdk-core/.github/workflows/semgrep.yml +0 -25
  149. package/sdk-core/core/src/worker/workflow/bridge.rs +0 -35
  150. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +0 -215
  151. package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +0 -2
  152. package/sdk-core/protos/api_upstream/Makefile +0 -80
  153. package/sdk-core/protos/api_upstream/api-linter.yaml +0 -40
  154. package/sdk-core/protos/api_upstream/buf.yaml +0 -9
  155. package/sdk-core/protos/api_upstream/build/go.mod +0 -7
  156. package/sdk-core/protos/api_upstream/build/go.sum +0 -5
  157. package/sdk-core/protos/api_upstream/go.mod +0 -6
  158. package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +0 -141
  159. /package/sdk-core/{.buildkite/docker → docker}/docker-compose-telem.yaml +0 -0
  160. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/docker-compose.yml +0 -0
  161. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/pipeline.yml +0 -0
  162. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/CODEOWNERS +0 -0
  163. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  164. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/publish-docs.yml +0 -0
  165. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
  166. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/LICENSE +0 -0
  167. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/README.md +0 -0
  168. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
  169. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
  170. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/common.proto +0 -0
  171. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
  172. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
  173. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/query.proto +0 -0
  174. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
  175. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
  176. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/update.proto +0 -0
  177. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
  178. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
  179. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/failure/v1/message.proto +0 -0
  180. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
  181. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/query/v1/message.proto +0 -0
  182. /package/sdk-core/{protos → sdk-core-protos/protos}/google/rpc/status.proto +0 -0
  183. /package/sdk-core/{protos → sdk-core-protos/protos}/grpc/health/v1/health.proto +0 -0
  184. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
  185. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
  186. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
  187. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/common/common.proto +0 -0
  188. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/core_interface.proto +0 -0
  189. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/external_data/external_data.proto +0 -0
  190. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
  191. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/Makefile +0 -0
  192. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/api-linter.yaml +0 -0
  193. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/buf.yaml +0 -0
  194. /package/sdk-core/{protos/api_upstream → sdk-core-protos/protos/testsrv_upstream}/dependencies/gogoproto/gogo.proto +0 -0
  195. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
  196. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
@@ -5,48 +5,42 @@ mod log_export;
5
5
  pub(crate) mod metrics;
6
6
  mod prometheus_server;
7
7
 
8
- use crate::telemetry::{
9
- log_export::{CoreLogExportLayer, CoreLogsOut},
10
- metrics::SDKAggSelector,
11
- prometheus_server::PromServer,
8
+ pub use metrics::{
9
+ build_otlp_metric_exporter, default_buckets_for, start_prometheus_metric_exporter,
10
+ MetricsCallBuffer,
12
11
  };
13
- use crossbeam::channel::Receiver;
12
+
13
+ pub use log_export::{CoreLogBuffer, CoreLogBufferedConsumer, CoreLogStreamConsumer};
14
+
15
+ use crate::telemetry::{log_export::CoreLogConsumerLayer, metrics::PrefixedMetricsMeter};
14
16
  use itertools::Itertools;
15
17
  use once_cell::sync::OnceCell;
16
- use opentelemetry::{
17
- metrics::{Meter, MeterProvider},
18
- runtime,
19
- sdk::{
20
- export::metrics::aggregation::{self, Temporality, TemporalitySelector},
21
- trace::Config,
22
- Resource,
23
- },
24
- KeyValue,
18
+ use opentelemetry::KeyValue;
19
+ use opentelemetry_sdk::{
20
+ metrics::{data::Temporality, reader::TemporalitySelector, InstrumentKind},
21
+ Resource,
25
22
  };
26
- use opentelemetry_otlp::WithExportConfig;
27
23
  use parking_lot::Mutex;
28
24
  use std::{
29
25
  cell::RefCell,
30
26
  collections::{HashMap, VecDeque},
31
- convert::TryInto,
32
27
  env,
33
- net::SocketAddr,
34
28
  sync::{
35
29
  atomic::{AtomicBool, Ordering},
36
30
  Arc,
37
31
  },
38
- time::Duration,
39
32
  };
40
33
  use temporal_sdk_core_api::telemetry::{
41
- CoreLog, CoreTelemetry, Logger, MetricTemporality, MetricsExporter, OtelCollectorOptions,
42
- TelemetryOptions, TraceExporter,
34
+ metrics::{CoreMeter, MetricKeyValue, NewAttributes, TemporalMeter},
35
+ CoreLog, CoreTelemetry, Logger, MetricTemporality, TelemetryOptions,
43
36
  };
44
- use tonic::metadata::MetadataMap;
45
37
  use tracing::{Level, Subscriber};
46
38
  use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Layer};
47
39
 
48
40
  const TELEM_SERVICE_NAME: &str = "temporal-core-sdk";
49
41
 
42
+ const FORWARD_LOG_BUFFER_SIZE: usize = 2048;
43
+
50
44
  /// Help you construct an [EnvFilter] compatible filter string which will forward all core module
51
45
  /// traces at `core_level` and all others (from 3rd party modules, etc) at `other_level`.
52
46
  pub fn construct_filter_string(core_level: Level, other_level: Level) -> String {
@@ -57,53 +51,75 @@ pub fn construct_filter_string(core_level: Level, other_level: Level) -> String
57
51
 
58
52
  /// Holds initialized tracing/metrics exporters, etc
59
53
  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<()>,
54
+ metric_prefix: String,
55
+ logs_out: Option<Mutex<CoreLogBuffer>>,
56
+ metrics: Option<Arc<dyn CoreMeter + 'static>>,
57
+ /// The tracing subscriber which is associated with this telemetry instance. May be `None` if
58
+ /// the user has not opted into any tracing configuration.
59
+ trace_subscriber: Option<Arc<dyn Subscriber + Send + Sync>>,
60
+ attach_service_name: bool,
66
61
  }
67
62
 
68
63
  impl TelemetryInstance {
69
64
  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<()>,
65
+ trace_subscriber: Option<Arc<dyn Subscriber + Send + Sync>>,
66
+ logs_out: Option<Mutex<CoreLogBuffer>>,
67
+ metric_prefix: String,
68
+ metrics: Option<Arc<dyn CoreMeter + 'static>>,
69
+ attach_service_name: bool,
76
70
  ) -> Self {
77
- let metrics = meter_provider.take().map(|mp| {
78
- let meter = mp.meter(TELEM_SERVICE_NAME);
79
- (mp, meter)
80
- });
81
71
  Self {
82
72
  metric_prefix,
83
73
  logs_out,
84
74
  metrics,
85
75
  trace_subscriber,
86
- prom_binding,
87
- _keepalive_rx: keepalive_rx,
76
+ attach_service_name,
88
77
  }
89
78
  }
90
79
 
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> {
80
+ /// Return the trace subscriber associated with the telemetry options/instance. Can be used
81
+ /// to manually set the default for a thread or globally using the `tracing` crate, or with
82
+ /// [set_trace_subscriber_for_current_thread].
83
+ pub fn trace_subscriber(&self) -> Option<Arc<dyn Subscriber + Send + Sync>> {
94
84
  self.trace_subscriber.clone()
95
85
  }
96
86
 
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
87
+ /// Some metric meters cannot be initialized until after a tokio runtime has started and after
88
+ /// other telemetry has initted (ex: prometheus). They can be attached here.
89
+ pub fn attach_late_init_metrics(&mut self, meter: Arc<dyn CoreMeter + 'static>) {
90
+ self.metrics = Some(meter);
100
91
  }
101
92
 
102
- /// Returns our wrapper for OTel metric meters, can be used to, ex: initialize clients
93
+ /// Returns our wrapper for metric meters, including the `metric_prefix` from
94
+ /// [TelemetryOptions]. This should be used to initialize clients or for any other
95
+ /// temporal-owned metrics. User defined metrics should use [Self::get_metric_meter].
96
+ pub fn get_temporal_metric_meter(&self) -> Option<TemporalMeter> {
97
+ self.metrics.clone().map(|m| {
98
+ let kvs = self.default_kvs();
99
+ let attribs = NewAttributes::new(kvs);
100
+ TemporalMeter::new(
101
+ Arc::new(PrefixedMetricsMeter::new(self.metric_prefix.clone(), m))
102
+ as Arc<dyn CoreMeter>,
103
+ attribs,
104
+ )
105
+ })
106
+ }
107
+
108
+ /// Returns our wrapper for metric meters, including attaching the service name if enabled.
103
109
  pub fn get_metric_meter(&self) -> Option<TemporalMeter> {
104
- self.metrics
105
- .as_ref()
106
- .map(|(_, m)| TemporalMeter::new(m, self.metric_prefix))
110
+ self.metrics.clone().map(|m| {
111
+ let kvs = self.default_kvs();
112
+ let attribs = NewAttributes::new(kvs);
113
+ TemporalMeter::new(m, attribs)
114
+ })
115
+ }
116
+
117
+ fn default_kvs(&self) -> Vec<MetricKeyValue> {
118
+ if self.attach_service_name {
119
+ vec![MetricKeyValue::new("service_name", TELEM_SERVICE_NAME)]
120
+ } else {
121
+ vec![]
122
+ }
107
123
  }
108
124
  }
109
125
 
@@ -129,18 +145,10 @@ pub fn remove_trace_subscriber_for_current_thread() {
129
145
  SUB_GUARD.with(|sg| sg.take());
130
146
  }
131
147
 
132
- fn metric_prefix(opts: &TelemetryOptions) -> &'static str {
133
- if opts.no_temporal_prefix_for_metrics {
134
- ""
135
- } else {
136
- "temporal_"
137
- }
138
- }
139
-
140
148
  impl CoreTelemetry for TelemetryInstance {
141
149
  fn fetch_buffered_logs(&self) -> Vec<CoreLog> {
142
150
  if let Some(logs_out) = self.logs_out.as_ref() {
143
- logs_out.lock().pop_iter().collect()
151
+ logs_out.lock().drain()
144
152
  } else {
145
153
  vec![]
146
154
  }
@@ -160,169 +168,72 @@ pub fn telemetry_init(opts: TelemetryOptions) -> Result<TelemetryInstance, anyho
160
168
  // in one case or the other. There does not seem to be a way to tell from the current runtime
161
169
  // handle if it is single or multithreaded. Additionally, we can isolate metrics work this
162
170
  // way which is nice.
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),
196
- )
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),
207
- )
208
- .with_filter(EnvFilter::new(filter)),
209
- )
210
- }
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
- }
217
- };
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 {
225
- PromServer::new(
226
- *addr,
227
- aggregator,
228
- metric_temporality_to_selector(opts.metric_temporality),
229
- &opts.global_tags,
230
- )
231
- })?;
232
- prom_binding = Some(srv.bound_addr());
233
- let mp = srv.exporter.meter_provider()?;
234
- runtime.spawn(async move { srv.run().await });
235
- Some(Box::new(mp) as Box<dyn MeterProvider + Send + Sync>)
236
- }
237
- MetricsExporter::Otel(OtelCollectorOptions {
238
- url,
239
- headers,
240
- metric_periodicity,
241
- }) => runtime.block_on(async {
242
- let metrics = opentelemetry_otlp::new_pipeline()
243
- .metrics(
244
- aggregator,
245
- metric_temporality_to_selector(opts.metric_temporality),
246
- runtime::Tokio,
247
- )
248
- .with_period(metric_periodicity.unwrap_or_else(|| Duration::from_secs(1)))
249
- .with_resource(default_resource(&opts.global_tags))
250
- .with_exporter(
251
- opentelemetry_otlp::new_exporter()
252
- .tonic()
253
- .with_endpoint(url.to_string())
254
- .with_metadata(MetadataMap::from_headers(headers.try_into()?)),
255
- )
256
- .build()?;
257
- Ok::<_, anyhow::Error>(Some(
258
- Box::new(metrics) as Box<dyn MeterProvider + Send + Sync>
259
- ))
260
- })?,
261
- }
262
- } else {
263
- None
264
- };
265
-
266
- if let Some(ref tracing) = opts.tracing {
267
- match &tracing.exporter {
268
- TraceExporter::Otel(OtelCollectorOptions { url, headers, .. }) => {
269
- runtime.block_on(async {
270
- let tracer_cfg =
271
- Config::default().with_resource(default_resource(&opts.global_tags));
272
- let tracer = opentelemetry_otlp::new_pipeline()
273
- .tracing()
274
- .with_exporter(
275
- opentelemetry_otlp::new_exporter()
276
- .tonic()
277
- .with_endpoint(url.to_string())
278
- .with_metadata(MetadataMap::from_headers(headers.try_into()?)),
171
+ // Parts of telem dat ====
172
+ let mut logs_out = None;
173
+ // =======================
174
+
175
+ // Tracing subscriber layers =========
176
+ let mut console_pretty_layer = None;
177
+ let mut console_compact_layer = None;
178
+ let mut forward_layer = None;
179
+ // ===================================
180
+
181
+ let tracing_sub = opts.logging.map(|logger| {
182
+ match logger {
183
+ Logger::Console { filter } => {
184
+ // This is silly dupe but can't be avoided without boxing.
185
+ if env::var("TEMPORAL_CORE_PRETTY_LOGS").is_ok() {
186
+ console_pretty_layer = Some(
187
+ tracing_subscriber::fmt::layer()
188
+ .with_target(false)
189
+ .event_format(
190
+ tracing_subscriber::fmt::format()
191
+ .pretty()
192
+ .with_source_location(false),
279
193
  )
280
- .with_trace_config(tracer_cfg)
281
- .install_batch(runtime::Tokio)?;
282
-
283
- let opentelemetry = tracing_opentelemetry::layer()
284
- .with_tracer(tracer)
285
- .with_filter(EnvFilter::new(&tracing.filter));
286
-
287
- export_layer = Some(opentelemetry);
288
- Result::<(), anyhow::Error>::Ok(())
289
- })?;
194
+ .with_filter(EnvFilter::new(filter)),
195
+ )
196
+ } else {
197
+ console_compact_layer = Some(
198
+ tracing_subscriber::fmt::layer()
199
+ .with_target(false)
200
+ .event_format(
201
+ tracing_subscriber::fmt::format()
202
+ .compact()
203
+ .with_source_location(false),
204
+ )
205
+ .with_filter(EnvFilter::new(filter)),
206
+ )
290
207
  }
291
- };
208
+ }
209
+ Logger::Forward { filter } => {
210
+ let (export_layer, lo) =
211
+ CoreLogConsumerLayer::new_buffered(FORWARD_LOG_BUFFER_SIZE);
212
+ logs_out = Some(Mutex::new(lo));
213
+ forward_layer = Some(export_layer.with_filter(EnvFilter::new(filter)));
214
+ }
215
+ Logger::Push { filter, consumer } => {
216
+ forward_layer =
217
+ Some(CoreLogConsumerLayer::new(consumer).with_filter(EnvFilter::new(filter)));
218
+ }
292
219
  };
293
-
294
220
  let reg = tracing_subscriber::registry()
295
221
  .with(console_pretty_layer)
296
222
  .with(console_compact_layer)
297
- .with(forward_layer)
298
- .with(export_layer);
223
+ .with(forward_layer);
299
224
 
300
225
  #[cfg(feature = "tokio-console")]
301
226
  let reg = reg.with(console_subscriber::spawn());
302
-
303
- tx.send(TelemetryInstance::new(
304
- Arc::new(reg),
305
- logs_out,
306
- metric_prefix,
307
- meter_provider,
308
- prom_binding,
309
- keepalive_rx,
310
- ))
311
- .expect("Must be able to send telem instance out of thread");
312
- // Now keep the thread alive until the telemetry instance is dropped by trying to send
313
- // something forever
314
- let _ = keepalive_tx.send(());
315
- Ok(())
227
+ Arc::new(reg) as Arc<dyn Subscriber + Send + Sync>
316
228
  });
317
- match rx.recv() {
318
- Ok(ti) => Ok(ti),
319
- Err(_) => {
320
- // Immediately join the thread since something went wrong in it
321
- jh.join().expect("Telemetry must init cleanly")?;
322
- // This can't happen. The rx channel can't be dropped unless the thread errored.
323
- unreachable!("Impossible error in telemetry init thread");
324
- }
325
- }
229
+
230
+ Ok(TelemetryInstance::new(
231
+ tracing_sub,
232
+ logs_out,
233
+ opts.metric_prefix,
234
+ opts.metrics,
235
+ opts.attach_service_name,
236
+ ))
326
237
  }
327
238
 
328
239
  /// Initialize telemetry/tracing globally. Useful for testing. Only takes affect when called
@@ -334,7 +245,9 @@ pub fn telemetry_init_global(opts: TelemetryOptions) -> Result<(), anyhow::Error
334
245
  .is_ok()
335
246
  {
336
247
  let ti = telemetry_init(opts)?;
337
- tracing::subscriber::set_global_default(ti.trace_subscriber())?;
248
+ if let Some(ts) = ti.trace_subscriber() {
249
+ tracing::subscriber::set_global_default(ts)?;
250
+ }
338
251
  }
339
252
  Ok(())
340
253
  }
@@ -351,21 +264,26 @@ fn default_resource(override_values: &HashMap<String, String>) -> Resource {
351
264
  Resource::new(default_resource_kvs().iter().cloned()).merge(&Resource::new(override_kvs))
352
265
  }
353
266
 
267
+ #[derive(Clone)]
268
+ struct ConstantTemporality(Temporality);
269
+ impl TemporalitySelector for ConstantTemporality {
270
+ fn temporality(&self, _: InstrumentKind) -> Temporality {
271
+ self.0
272
+ }
273
+ }
354
274
  fn metric_temporality_to_selector(
355
275
  t: MetricTemporality,
356
276
  ) -> impl TemporalitySelector + Send + Sync + Clone {
357
277
  match t {
358
- MetricTemporality::Cumulative => {
359
- aggregation::constant_temporality_selector(Temporality::Cumulative)
360
- }
361
- MetricTemporality::Delta => aggregation::constant_temporality_selector(Temporality::Delta),
278
+ MetricTemporality::Cumulative => ConstantTemporality(Temporality::Cumulative),
279
+ MetricTemporality::Delta => ConstantTemporality(Temporality::Delta),
362
280
  }
363
281
  }
364
282
 
365
283
  #[cfg(test)]
366
284
  pub mod test_initters {
367
285
  use super::*;
368
- use temporal_sdk_core_api::telemetry::{TelemetryOptionsBuilder, TraceExportConfig};
286
+ use temporal_sdk_core_api::telemetry::TelemetryOptionsBuilder;
369
287
 
370
288
  #[allow(dead_code)] // Not always used, called to enable for debugging when needed
371
289
  pub fn test_telem_console() {
@@ -379,29 +297,7 @@ pub mod test_initters {
379
297
  )
380
298
  .unwrap();
381
299
  }
382
-
383
- #[allow(dead_code)] // Not always used, called to enable for debugging when needed
384
- pub fn test_telem_collector() {
385
- telemetry_init_global(
386
- TelemetryOptionsBuilder::default()
387
- .logging(Logger::Console {
388
- filter: construct_filter_string(Level::DEBUG, Level::WARN),
389
- })
390
- .tracing(TraceExportConfig {
391
- filter: construct_filter_string(Level::DEBUG, Level::WARN),
392
- exporter: TraceExporter::Otel(OtelCollectorOptions {
393
- url: "grpc://localhost:4317".parse().unwrap(),
394
- headers: Default::default(),
395
- metric_periodicity: None,
396
- }),
397
- })
398
- .build()
399
- .unwrap(),
400
- )
401
- .unwrap();
402
- }
403
300
  }
404
- use crate::telemetry::metrics::TemporalMeter;
405
301
  #[cfg(test)]
406
302
  pub use test_initters::*;
407
303
 
@@ -1,52 +1,57 @@
1
- use crate::telemetry::default_resource;
2
1
  use hyper::{
3
2
  header::CONTENT_TYPE,
4
3
  server::conn::AddrIncoming,
5
4
  service::{make_service_fn, service_fn},
6
5
  Body, Method, Request, Response, Server,
7
6
  };
8
- use opentelemetry::sdk::{
9
- export::metrics::{aggregation::TemporalitySelector, AggregatorSelector},
10
- metrics::{controllers, processors},
11
- };
12
- use opentelemetry_prometheus::{ExporterBuilder, PrometheusExporter};
13
- use prometheus::{Encoder, TextEncoder};
14
- use std::{collections::HashMap, convert::Infallible, net::SocketAddr, sync::Arc, time::Duration};
7
+ use opentelemetry_prometheus::PrometheusExporter;
8
+ use opentelemetry_sdk::metrics::reader::AggregationSelector;
9
+ use prometheus::{Encoder, Registry, TextEncoder};
10
+ use std::{convert::Infallible, net::SocketAddr};
11
+ use temporal_sdk_core_api::telemetry::PrometheusExporterOptions;
15
12
 
16
13
  /// Exposes prometheus metrics for scraping
17
14
  pub(super) struct PromServer {
18
15
  bound_addr: AddrIncoming,
19
- pub exporter: Arc<PrometheusExporter>,
16
+ registry: Registry,
20
17
  }
21
18
 
22
19
  impl PromServer {
23
20
  pub fn new(
24
- addr: SocketAddr,
25
- aggregation: impl AggregatorSelector + Send + Sync + 'static,
26
- temporality: impl TemporalitySelector + Send + Sync + 'static,
27
- tags: &HashMap<String, String>,
28
- ) -> Result<Self, anyhow::Error> {
29
- let controller =
30
- controllers::basic(processors::factory(aggregation, temporality).with_memory(true))
31
- // Because Prom is pull-based, make this always refresh
32
- .with_collect_period(Duration::from_secs(0))
33
- .with_resource(default_resource(tags))
34
- .build();
35
- let exporter = ExporterBuilder::new(controller).try_init()?;
36
- let bound_addr = AddrIncoming::bind(&addr)?;
37
- Ok(Self {
38
- exporter: Arc::new(exporter),
39
- bound_addr,
40
- })
21
+ opts: &PrometheusExporterOptions,
22
+ aggregation: impl AggregationSelector + Send + Sync + 'static,
23
+ ) -> Result<(Self, PrometheusExporter), anyhow::Error> {
24
+ let registry = Registry::new();
25
+ let exporter = opentelemetry_prometheus::exporter()
26
+ .with_aggregation_selector(aggregation)
27
+ .without_scope_info()
28
+ .with_registry(registry.clone());
29
+ let exporter = if !opts.counters_total_suffix {
30
+ exporter.without_counter_suffixes()
31
+ } else {
32
+ exporter
33
+ };
34
+ let exporter = if !opts.unit_suffix {
35
+ exporter.without_units()
36
+ } else {
37
+ exporter
38
+ };
39
+ let bound_addr = AddrIncoming::bind(&opts.socket_addr)?;
40
+ Ok((
41
+ Self {
42
+ bound_addr,
43
+ registry,
44
+ },
45
+ exporter.build()?,
46
+ ))
41
47
  }
42
48
 
43
49
  pub async fn run(self) -> hyper::Result<()> {
44
50
  // Spin up hyper server to serve metrics for scraping. We use hyper since we already depend
45
51
  // on it via Tonic.
46
- let expclone = self.exporter.clone();
47
52
  let svc = make_service_fn(move |_conn| {
48
- let expclone = expclone.clone();
49
- async move { Ok::<_, Infallible>(service_fn(move |req| metrics_req(req, expclone.clone()))) }
53
+ let regclone = self.registry.clone();
54
+ async move { Ok::<_, Infallible>(service_fn(move |req| metrics_req(req, regclone.clone()))) }
50
55
  });
51
56
  let server = Server::builder(self.bound_addr).serve(svc);
52
57
  server.await
@@ -60,13 +65,13 @@ impl PromServer {
60
65
  /// Serves prometheus metrics in the expected format for scraping
61
66
  async fn metrics_req(
62
67
  req: Request<Body>,
63
- exporter: Arc<PrometheusExporter>,
68
+ registry: Registry,
64
69
  ) -> Result<Response<Body>, hyper::Error> {
65
70
  let response = match (req.method(), req.uri().path()) {
66
71
  (&Method::GET, "/metrics") => {
67
72
  let mut buffer = vec![];
68
73
  let encoder = TextEncoder::new();
69
- let metric_families = exporter.registry().gather();
74
+ let metric_families = registry.gather();
70
75
  encoder.encode(&metric_families, &mut buffer).unwrap();
71
76
 
72
77
  Response::builder()