diff --git a/sdk/core/core-tracing/review/core-tracing.api.md b/sdk/core/core-tracing/review/core-tracing.api.md index d4f53be814e2..2b01b410a6ab 100644 --- a/sdk/core/core-tracing/review/core-tracing.api.md +++ b/sdk/core/core-tracing/review/core-tracing.api.md @@ -30,6 +30,11 @@ export interface OperationTracingOptions { tracingContext?: TracingContext; } +// @public +export type Resolved = T extends { + then(onfulfilled: infer F): any; +} ? F extends (value: infer V) => any ? Resolved : never : T; + // @public export type SpanStatus = SpanStatusSuccess | SpanStatusError; @@ -57,7 +62,7 @@ export interface TracingClient { withContext ReturnType>(context: TracingContext, callback: Callback, ...callbackArgs: CallbackArgs): ReturnType; withSpan) => ReturnType>(name: string, operationOptions: Options, callback: Callback, spanOptions?: TracingSpanOptions): Promise>; + }, Callback extends (updatedOptions: Options, span: Omit) => ReturnType>(name: string, operationOptions: Options, callback: Callback, spanOptions?: TracingSpanOptions): Promise>>; } // @public diff --git a/sdk/core/core-tracing/src/index.ts b/sdk/core/core-tracing/src/index.ts index 423149e112f8..dd244d07157f 100644 --- a/sdk/core/core-tracing/src/index.ts +++ b/sdk/core/core-tracing/src/index.ts @@ -5,6 +5,7 @@ export { Instrumenter, InstrumenterSpanOptions, OperationTracingOptions, + Resolved, SpanStatus, SpanStatusError, SpanStatusSuccess, diff --git a/sdk/core/core-tracing/src/interfaces.ts b/sdk/core/core-tracing/src/interfaces.ts index acfec30a582d..a9c340d4d8ec 100644 --- a/sdk/core/core-tracing/src/interfaces.ts +++ b/sdk/core/core-tracing/src/interfaces.ts @@ -1,6 +1,16 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +/** + * A narrower version of TypeScript 4.5's Awaited type which Recursively + * unwraps the "awaited type", emulating the behavior of `await`. + */ +export type Resolved = T extends { then(onfulfilled: infer F): any } // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped + ? F extends (value: infer V) => any // if the argument to `then` is callable, extracts the first argument + ? Resolved // recursively unwrap the value + : never // the argument to `then` was not callable + : T; // non-object or non-thenable + /** * Represents a client that can integrate with the currently configured {@link Instrumenter}. * @@ -12,6 +22,8 @@ export interface TracingClient { * * This is the primary interface for using Tracing and will handle error recording as well as setting the status on the span. * + * Both synchronous and asynchronous functions will be awaited in order to reflect the result of the callback on the span. + * * Example: * * ```ts @@ -32,7 +44,7 @@ export interface TracingClient { operationOptions: Options, callback: Callback, spanOptions?: TracingSpanOptions - ): Promise>; + ): Promise>>; /** * Starts a given span but does not set it as the active span. * diff --git a/sdk/core/core-tracing/src/tracingClient.ts b/sdk/core/core-tracing/src/tracingClient.ts index fa39b03d9214..bc32cc55a6c6 100644 --- a/sdk/core/core-tracing/src/tracingClient.ts +++ b/sdk/core/core-tracing/src/tracingClient.ts @@ -3,6 +3,7 @@ import { OperationTracingOptions, + Resolved, TracingClient, TracingClientOptions, TracingContext, @@ -64,14 +65,14 @@ export function createTracingClient(options: TracingClientOptions): TracingClien operationOptions: Options, callback: Callback, spanOptions?: TracingSpanOptions - ): Promise> { + ): Promise>> { const { span, updatedOptions } = startSpan(name, operationOptions, spanOptions); try { const result = await withContext(updatedOptions.tracingOptions!.tracingContext!, () => Promise.resolve(callback(updatedOptions, span)) ); span.setStatus({ status: "success" }); - return result; + return result as ReturnType; } catch (err) { span.setStatus({ status: "error", error: err }); throw err;