diff --git a/src/OpenTelemetry/.publicApi/net452/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net452/PublicAPI.Unshipped.txt
index e69de29bb2d..8b90281a056 100644
--- a/src/OpenTelemetry/.publicApi/net452/PublicAPI.Unshipped.txt
+++ b/src/OpenTelemetry/.publicApi/net452/PublicAPI.Unshipped.txt
@@ -0,0 +1 @@
+static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool
\ No newline at end of file
diff --git a/src/OpenTelemetry/.publicApi/net46/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net46/PublicAPI.Unshipped.txt
index e69de29bb2d..6779d236a29 100644
--- a/src/OpenTelemetry/.publicApi/net46/PublicAPI.Unshipped.txt
+++ b/src/OpenTelemetry/.publicApi/net46/PublicAPI.Unshipped.txt
@@ -0,0 +1 @@
+static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool
diff --git a/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt
index e69de29bb2d..6779d236a29 100644
--- a/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt
+++ b/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt
@@ -0,0 +1 @@
+static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool
diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt
index e69de29bb2d..6779d236a29 100644
--- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt
+++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt
@@ -0,0 +1 @@
+static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool
diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md
index a0b04e6c57e..e3770cadff8 100644
--- a/src/OpenTelemetry/CHANGELOG.md
+++ b/src/OpenTelemetry/CHANGELOG.md
@@ -9,6 +9,8 @@ please check the latest changes
## Unreleased
+* Added `ForceFlush` to `TracerProvider`. ([#1837](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1837))
+
## 1.0.1
Released 2021-Feb-10
diff --git a/src/OpenTelemetry/Trace/TracerProviderExtensions.cs b/src/OpenTelemetry/Trace/TracerProviderExtensions.cs
index 302f85d5173..cfa331e179d 100644
--- a/src/OpenTelemetry/Trace/TracerProviderExtensions.cs
+++ b/src/OpenTelemetry/Trace/TracerProviderExtensions.cs
@@ -43,6 +43,52 @@ public static TracerProvider AddProcessor(this TracerProvider provider, BaseProc
return provider;
}
+ ///
+ /// Flushes the all the processors at TracerProviderSdk, blocks the current thread until flush
+ /// completed, shutdown signaled or timed out.
+ ///
+ /// TracerProviderSdk instance on which ForceFlush will be called.
+ ///
+ /// The number of milliseconds to wait, or Timeout.Infinite to
+ /// wait indefinitely.
+ ///
+ ///
+ /// Returns true when force flush succeeded; otherwise, false.
+ ///
+ ///
+ /// Thrown when the timeoutMilliseconds is smaller than -1.
+ ///
+ ///
+ /// This function guarantees thread-safety.
+ ///
+ public static bool ForceFlush(this TracerProvider provider, int timeoutMilliseconds = Timeout.Infinite)
+ {
+ if (provider == null)
+ {
+ throw new ArgumentNullException(nameof(provider));
+ }
+
+ if (provider is TracerProviderSdk tracerProviderSdk)
+ {
+ if (timeoutMilliseconds < 0 && timeoutMilliseconds != Timeout.Infinite)
+ {
+ throw new ArgumentOutOfRangeException(nameof(timeoutMilliseconds), timeoutMilliseconds, "timeoutMilliseconds should be non-negative.");
+ }
+
+ try
+ {
+ return tracerProviderSdk.OnForceFlush(timeoutMilliseconds);
+ }
+ catch (Exception ex)
+ {
+ OpenTelemetrySdkEventSource.Log.TracerProviderException(nameof(tracerProviderSdk.OnForceFlush), ex);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
///
/// Attempts to shutdown the TracerProviderSdk, blocks the current thread until
/// shutdown completed or timed out.
diff --git a/src/OpenTelemetry/Trace/TracerProviderSdk.cs b/src/OpenTelemetry/Trace/TracerProviderSdk.cs
index d0759533a5e..a2e6dff3ba4 100644
--- a/src/OpenTelemetry/Trace/TracerProviderSdk.cs
+++ b/src/OpenTelemetry/Trace/TracerProviderSdk.cs
@@ -207,6 +207,11 @@ internal TracerProviderSdk AddProcessor(BaseProcessor processor)
return this;
}
+ internal bool OnForceFlush(int timeoutMilliseconds)
+ {
+ return this.processor?.ForceFlush(timeoutMilliseconds) ?? true;
+ }
+
///
/// Called by Shutdown. This function should block the current
/// thread until shutdown completed or timed out.
diff --git a/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs b/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs
index e193cb9b5b6..64891ae7098 100644
--- a/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs
+++ b/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs
@@ -398,6 +398,21 @@ public void TracerProviderSdkBuildsWithSDKResource()
Assert.Single(versionAttribute);
}
+ [Fact]
+ public void TracerProviderSdkFlushesProcessorForcibly()
+ {
+ using TestActivityProcessor testActivityProcessor = new TestActivityProcessor();
+
+ using var tracerProvider = Sdk.CreateTracerProviderBuilder()
+ .AddProcessor(testActivityProcessor)
+ .Build();
+
+ var isFlushed = tracerProvider.ForceFlush();
+
+ Assert.True(isFlushed);
+ Assert.True(testActivityProcessor.ForceFlushCalled);
+ }
+
public void Dispose()
{
GC.SuppressFinalize(this);