Limit threads to 1 (to force tests to run
consecutively) to temporarily fix random [failures](https://github.com/open-telemetry/opentelemetry-rust/actions/runs/6915742069/job/18815025248)
during `opentelemetry-jaeger` tests, due to environment variable updates
from parallel tests
If you run this command line multiple times, you should be able to
reproduce it (`test_resolve_timeout` and `test_resolve_endpoint` are
updating some environment variables)
```shell
cargo test --manifest-path=opentelemetry-jaeger/Cargo.toml --all-features collector -- --test-threads=5
```
* Add support for concurrent exports
Applications generating significant span volume can end up dropping data
due to the synchronous export step. According to the opentelemetry spec,
This function will never be called concurrently for the same exporter
instance. It can be called again only after the current call returns.
However, it does not place a restriction on concurrent I/O or anything
of that nature. There is an [ongoing discussion] about tweaking the
language to make this more clear.
With that in mind, this commit makes the exporters return a future that
can be spawned concurrently. Unfortunately, this means that the
`export()` method can no longer be async while taking &mut self. The
latter is desirable to enforce the no concurrent calls line of the spec,
so the choice is made here to return a future instead with the lifetime
decoupled from self. This resulted in a bit of additional verbosity, but
for the most part the async code can still be shoved into an async fn
for the ergonomics.
The main exception to this is the `jaeger` exporter which internally
requires a bunch of mutable references. I plan to discuss with the
opentelemetry team the overall goal of this PR and get buy-in before
making more invasive changes to support this in the jaeger exporter.
[ongoing discussion]: https://github.com/open-telemetry/opentelemetry-specification/issues/2434
* SpanProcessor directly manages concurrent exports
Prior, export tasks were run in "fire and forget" mode with
runtime::spawn. SpanProcessor now manages tasks directly using
FuturesUnordered. This enables limiting overall concurrency (and thus
memory footprint). Additionally, flush and shutdown logic now spawn an
additional task for any unexported spans and wait on _all_ outstanding
tasks to complete before returning.
* Add configuration for BSP max_concurrent_exports
Users may desire to control the level of export concurrency in the batch
span processor. There are two special values:
max_concurrent_exports = 0: no bound on concurrency
max_concurrent_exports = 1: no concurrency, makes everything
synchronous on the messaging task.
* Implement new SpanExporter API for Jaeger
Key points
- decouple exporter from uploaders via channel and spawned task
- some uploaders are a shared I/O resource and cannot be multiplexed
- necessitates a task queue
- eg, HttpClient will spawn many I/O tasks internally, AgentUploader
is a single I/O resource. Different level of abstraction.
- Synchronous API not supported without a Runtime argument. I updated
the API to thread one through, but maybe this is undesirable. I'm also
exploiting the fact in the Actix examples that it uses Tokio under the
hood to pass through the Tokio runtime token.
- Tests pass save for a couple of flakey environment ones which is
likely a race condition.
* Reduce dependencies on futures
The minimal necessary futures library (core, util, futures proper) is
now used in all packages touched by the concurrent exporters work.
* Remove runtime from Jaeger's install_simple
To keep the API _actually_ simple, we now leverage a thread to run the
jaeger exporter internals.
* Add Arc lost in a rebase
* Fix OTEL_BSP_MAX_CONCURRENT_EXPORTS name and value
Per PR feedback, the default should match the previous behavior of 1
batch at a time.
* Fix remaining TODOs
This finishes the remaining TODOs on the concurrent-exports branch. The
major change included here adds shutdown functionality to the jaeger
exporter which ensures the exporter has finished its tasks before
exiting.
* Restore lint.sh script
This was erroneously committed.
* Make max concurrent exports env configurable
OTEL_BSP_MAX_CONCURRENT_EXPORTS may now be specified in the environment
to configure the number of max concurrent exports. This configurable now
has parity with the other options of the span_processor.
* chore: update the NoHttpClient error message
Adds a hint to the error message to make it better understandable to users how to resolve the error
* chore: Use fully qualified stream import (metrics)
* Add opentelemetry-dynatrace crate
Configure the async runtime (Tokio, async-std, ...) in Rust using
`with_runtime(runtime)` on the trace pipeline builders instead of using
cargo features.
The main advantages of using Rust code is that cargo doesn't have a way
of describing mutually exclusive features at the moment. We currently
fall back to Tokio if multiple runtime features are enabled. This can be
confusing, especially if a runtime feature is enabled by another crate.
Choosing the runtime in Rust code means the entire trace pipeline
configuration is in one place.
`tonic` and `grpcio` take different approaches in serializing and sending spans. This change use an enum to represent the two grpc layers. If users want to bring their own grpc layer, they can implement `TracerExporter` and `SpanExporter` and then install it.
This adds a suite of tests to ensure the global tracer provider shuts down properly using different runtimes. For optimal performance it is often preferable to spawn shutdown tasks using `tokio::spawn` instead of `tokio::spawn_blocking`, but in order to have a consistent API between blocking and non-blocking programs, then shutdown code will block on some tasks. This can cause deadlocks with single-threaded runtimes, the current solution is to spawn the background task in a separate thread if single threaded runtime features are present.
Add support for the [tonic](https://github.com/hyperium/tonic) implementation of the gRPC transport layer to `opentelemetry-otlp`.
- Use tonic as the underlying gRPC transport layer (default)
- Optional: TLS support using rustls
- Optional: Use the platform's native certificate store
- Optional: Use an async client
This makes working with cargo easier, because many commands (like cargo
check, cargo test) will apply to all crates by default, rather than
only selecting the crate in the top-level directory.
Added optional `serialize` feature that allows `SpanData` to be
serialized/deserialized using the `serde` crate.
Also added a basic unit test for `SpanData` to test serialization and
deserialization.
Fixes: #58.
Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>