From d75ed3a8823818018356d8965054300e15040cb4 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Thu, 5 Jul 2018 17:15:54 +0200 Subject: [PATCH 1/3] Set the scope_manager RFC to Test. --- rfc/scope_manager.md | 2 +- specification.md | 73 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/rfc/scope_manager.md b/rfc/scope_manager.md index 66a3e35..dfad6f0 100644 --- a/rfc/scope_manager.md +++ b/rfc/scope_manager.md @@ -1,6 +1,6 @@ # Scope Manager -**Current State:** Draft +**Current State:** Test **Author:** [carlosalberto](https://github.com/carlosalberto) In the OpenTracing specification, under the "Optional API Elements" section, it is mentioned languages may choose to provide utilities to pass an active **Span** around a single process. diff --git a/specification.md b/specification.md index 1b1ee1d..c323936 100644 --- a/specification.md +++ b/specification.md @@ -117,16 +117,30 @@ These can all be valid timing diagrams for children that "FollowFrom" a parent. ## The OpenTracing API -There are three critical and inter-related types in the OpenTracing specification: `Tracer`, `Span`, and `SpanContext`. Below, we go through the behaviors of each type; roughly speaking, each behavior becomes a "method" in a typical programming language, though it may actually be a set of related sibling methods due to type overloading and so on. +There are three critical and inter-related types in the OpenTracing specification: `Tracer`, `Span`, and `SpanContext`, as well as two optional helper types: `ScopeManager` and `Scope`. Below, we go through the behaviors of each type; roughly speaking, each behavior becomes a "method" in a typical programming language, though it may actually be a set of related sibling methods due to type overloading and so on. When we discuss "optional" parameters, it is understood that different languages have different ways to construe such concepts. For example, in Go we might use the "functional Options" idiom, whereas in Java we might use a builder pattern. +### Within-process `Span` propagation + +For any thread or execution unit, at most one `Span` may be active, and it is important that such `Span` is available at any point down the execution chain, in order to define proper **Reference** relationships among `Span`s. + +For platforms where the call-context is explicitly propagated down the execution chain -such as `Go`-, such context can be used to store the active `Span` at all times. + +For platforms not propagating a call-context, it is inconvenient to pass the active `Span` from function to function manually. For those platforms, the `Tracer` interface must contain a `ScopeManager` instance that stores and handles the active `Span` through a container interface, called `Scope`. + ### `Tracer` -The `Tracer` interface creates `Span`s and understands how to `Inject` -(serialize) and `Extract` (deserialize) them across process boundaries. +The `Tracer` interface creates `Span`s, understands how to `Inject` +(serialize) and `Extract` (deserialize) them across process boundaries, and optionally contains a `ScopeManager` instance to handle the active `Span`. Formally, it has the following capabilities: +#### Retrieve the `ScopeManager` (Optional) + +There should be no parameters. + +**Returns** the used `ScopeManager` instance to set and retrieve the active `Span`. The mentioned active instance is additinaly used by default as the implicit parent for newly created `Span`s, in case no **references** were provided. + #### Start a new `Span` Required parameters @@ -144,11 +158,24 @@ For example, here are potential **operation names** for a `Span` that gets hypot Optional parameters - Zero or more **references** to related `SpanContext`s, including a shorthand for `ChildOf` and `FollowsFrom` reference types if possible. +- An optional explicit **ignore active Span** boolean specifying whether the active `Span` should be ignored and not used as the implicit parent, in case no **references** were provided. - An optional explicit **start timestamp**; if omitted, the current walltime is used by default - Zero or more **tags** **Returns** a `Span` instance that's already started (but not `Finish`ed) +#### Start a `Scope` with a new `Span` (Optional) + +This operation does the same as **Start a new `Span`**, in addition to setting the newly created `Span` as the active instance for the current thread or execution unit through the contained `ScopeManager` instance. + +It is **highly** encouraged that the name for this operation includes a `Scope` sufix, in order to make clear the type of the returned instance. + +Parameters are the same as **Start a new Span**, with the addition of: + +- A **finish Span on close** boolean specifying whether the contained `Span` should be closed upon `Scope` being `Close`d. This is a special parameter that can be either required or optional (along with a default value), depending on the specific needs of the platform. + +**Returns** a `Scope` instance containing a `Span` instance that's already started (but not `Finish`ed). + #### Inject a `SpanContext` into a carrier Required parameters @@ -250,6 +277,46 @@ In OpenTracing we force `SpanContext` instances to be **immutable** in order to This is modeled in different ways depending on the language, but semantically the caller should be able to efficiently iterate through all baggage items in one pass given a `SpanContext` instance. +### `ScopeManager` + +The `ScopeManager` interface sets and retrieves the active `Span`, working along the `Scope` container interface. +Formally, it has the following capabilities: + +#### Activate a `Span` + +Prior to setting a provided `Span` as active for the current thread or execution unit, the previously active instance needs to be stashed away, so it can be restored afterwards. + +Required parameters + +- **span**, the `Span` instance to be set as active. +- **finish Span on close**, a boolean value specifying whether the `Span` should be `Finish`ed upon being deactivated through its container `Scope` being `Close`d. + +**Returns** a `Scope` instance containing the newly activated `Span`. + +#### Retrieve the active `Span` + +There should be no parameters. + +**Returns** a `Scope` instance containing the active `Span`, or else `null` if there's none for the current thread or execution unit. + +### `Scope` + +The `Scope` interface acts as a simple container for the active `Span`,and it not guaranteed to be thread-safe. It has the following capabilities: + +#### Retrieve the contained `Span` + +There should be no parameters. + +**Returns** the contained `Span`. The returned value can never be `null`. + +#### Close the `Scope` + +Closing the `Scope` will make its contained `Span` stop being the currently active instance for the thread or execution unit, optionally `Finish`ing it depending on the **finish Span on close** parameter that was provided during activation. + +If the `Scope` instance being `Close`d does not correspond to the actually active one, no action will be performed. An additional side effect will be restoring the previously active `Span` instance along with its `Scope` container. + +There should be no parameters. + ### `NoopTracer` All OpenTracing language APIs must also provide some sort of `NoopTracer` implementation which can be used to flag-control OpenTracing or inject something harmless for tests (et cetera). In some cases (for example, Java) the `NoopTracer` may be in its own packaging artifact. From ce006084e685eaaca6b3a8e15c6f871499171200 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Tue, 13 Nov 2018 18:47:39 +0100 Subject: [PATCH 2/3] Minor corrections. --- specification.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specification.md b/specification.md index c323936..ecac41a 100644 --- a/specification.md +++ b/specification.md @@ -139,7 +139,7 @@ Formally, it has the following capabilities: There should be no parameters. -**Returns** the used `ScopeManager` instance to set and retrieve the active `Span`. The mentioned active instance is additinaly used by default as the implicit parent for newly created `Span`s, in case no **references** were provided. +**Returns** the used `ScopeManager` instance to set and retrieve the active `Scope` and `Span`. The mentioned active instance is additinaly used by default as the implicit parent for newly created `Span`s, in case no **references** were provided. #### Start a new `Span` @@ -168,7 +168,7 @@ Optional parameters This operation does the same as **Start a new `Span`**, in addition to setting the newly created `Span` as the active instance for the current thread or execution unit through the contained `ScopeManager` instance. -It is **highly** encouraged that the name for this operation includes a `Scope` sufix, in order to make clear the type of the returned instance. +It is **highly** encouraged that language implementations (methods or fields) of this operation include a `Scope` suffix, in order to make clear the type of the returned instance. Parameters are the same as **Start a new Span**, with the addition of: @@ -279,7 +279,7 @@ This is modeled in different ways depending on the language, but semantically th ### `ScopeManager` -The `ScopeManager` interface sets and retrieves the active `Span`, working along the `Scope` container interface. +The `ScopeManager` interface sets and retrieves the active `Scope` and `Span`. Formally, it has the following capabilities: #### Activate a `Span` @@ -301,7 +301,7 @@ There should be no parameters. ### `Scope` -The `Scope` interface acts as a simple container for the active `Span`,and it not guaranteed to be thread-safe. It has the following capabilities: +The `Scope` interface acts as a simple container for the active `Span`,and it is not guaranteed to be thread-safe. It has the following capabilities: #### Retrieve the contained `Span` From 434e6764129e0eb02d27fd096191ca52cc8bb2c9 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Wed, 14 Nov 2018 16:21:30 +0100 Subject: [PATCH 3/3] Update the RFC with our latest OT Java iteration. --- rfc/scope_manager.md | 11 +++++++---- specification.md | 37 +++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/rfc/scope_manager.md b/rfc/scope_manager.md index dfad6f0..6b550b8 100644 --- a/rfc/scope_manager.md +++ b/rfc/scope_manager.md @@ -23,15 +23,17 @@ New `ScopeManager` and `Scope` interfaces are added to the specification, and th The `ScopeManager` interface allows setting the active `Span` in a call-context storage section, and has the following members: -* **activate**, capability to set the specified `Span` as the active one for the current call-context, returning a `Scope` containing it. A required boolean parameter **finish span on close** will mark whether the returned `Scope` should, upon deactivation, **finish** the contained `Span`. -* **active**, the `Scope` containing the current active `Span` if any, or else null/nothing. +* **activate**, capability to set the specified `Span` as the active one for the current call-context, returning a `Scope` to later end its active period. + An **optional** feature to optionally **finish** the `Span` upon `Scope` deactivation may be provided, depending on its suitability for the language. It would require a boolean parameter **finish span on close**. +* **active Span**, the `Span` that is currently active, if any, or else null/nothing. +* **active**, the corresponding `Scope` for the current active `Span` if any, or else null/nothing. ## Scope The `Scope` interface acts as a container of the active `Span` for the current-call context, and has the following members: -* **span**, the contained active `Span` for this call-context. It will never be null/nothing. * **close**, marking the end of the active period for the current `Span`, and optionally **finishing** it. Calling it more than once leads to undefined behavior. +* **span** (optional), the related active `Span` for this call-context, depending on its suitability for the language. It will never be null/nothing. If the language supports some kind of auto finishing statement (such as `try` for Java, or `with` for Python), `Scope` should adhere to such convention. Additionally, `Scope` is not guaranteed to be thread-safe. @@ -40,7 +42,8 @@ If the language supports some kind of auto finishing statement (such as `try` fo The `Tracer` interface will be extended with: * **scope manager**, the `ScopeManager` tracking the active `Span` for this instance. -* **start active span**, a new behavior for starting a new `Span`, which will be automatically marked as active for the current call-context. It will return a `Scope`. A parameter **finish span on close** will mark whether the `Scope` should, upon deactivation, **finish** the contained `Span`. A default value for this parameter may be provided, depending on the suitability for the language and its use cases. +* **start active span** (optional), a new behavior for starting a new `Span`, which will be automatically marked as active for the current call-context. It will return a `Scope`. + An **optional** feature to optionally finish `Span` upon `Scope` deactivation may be provided, depending on its suitability for the language. It would require a boolean parameter **finish span on close**. A default value for this parameter may be provided, depending again on the suitability for the language and its use cases. * Both **start span** and **start active span** will implicitly use any active `Span` as the parent for newly created `Span`s (with a `ChildOf` relationship), unless the parent is explicitly specified, or (the new) **ignore active span** parameter is specified (in which case the resulting `Span` will have no parent at all). # Use Cases diff --git a/specification.md b/specification.md index ecac41a..9032d59 100644 --- a/specification.md +++ b/specification.md @@ -127,7 +127,7 @@ For any thread or execution unit, at most one `Span` may be active, and it is im For platforms where the call-context is explicitly propagated down the execution chain -such as `Go`-, such context can be used to store the active `Span` at all times. -For platforms not propagating a call-context, it is inconvenient to pass the active `Span` from function to function manually. For those platforms, the `Tracer` interface must contain a `ScopeManager` instance that stores and handles the active `Span` through a container interface, called `Scope`. +For platforms not propagating a call-context, it is inconvenient to pass the active `Span` from function to function manually. For those platforms, the `Tracer` interface must contain a `ScopeManager` instance that stores and handles the active `Span` with the help of the `Scope` interface to end its active period. ### `Tracer` @@ -139,7 +139,7 @@ Formally, it has the following capabilities: There should be no parameters. -**Returns** the used `ScopeManager` instance to set and retrieve the active `Scope` and `Span`. The mentioned active instance is additinaly used by default as the implicit parent for newly created `Span`s, in case no **references** were provided. +**Returns** the used `ScopeManager` instance to set and retrieve the active `Span` and its corresponding `Scope`. The mentioned active instance is additionally used by default as the implicit parent for newly created `Span`s, in case no **references** were provided. #### Start a new `Span` @@ -174,7 +174,9 @@ Parameters are the same as **Start a new Span**, with the addition of: - A **finish Span on close** boolean specifying whether the contained `Span` should be closed upon `Scope` being `Close`d. This is a special parameter that can be either required or optional (along with a default value), depending on the specific needs of the platform. -**Returns** a `Scope` instance containing a `Span` instance that's already started (but not `Finish`ed). +**Returns** a `Scope` instance corresponding to the `Span` that was started (but not `Finish`ed). + +Note: This operation is defined as optional, and its existence will depend on its suitability for the thread model, language semantics, API guidelines and other considerations for every given language. #### Inject a `SpanContext` into a carrier @@ -279,7 +281,7 @@ This is modeled in different ways depending on the language, but semantically th ### `ScopeManager` -The `ScopeManager` interface sets and retrieves the active `Scope` and `Span`. +The `ScopeManager` interface sets and retrieves the active `Span` and its corresponding `Scope`. Formally, it has the following capabilities: #### Activate a `Span` @@ -289,34 +291,45 @@ Prior to setting a provided `Span` as active for the current thread or execution Required parameters - **span**, the `Span` instance to be set as active. -- **finish Span on close**, a boolean value specifying whether the `Span` should be `Finish`ed upon being deactivated through its container `Scope` being `Close`d. +- **finish Span on close** (optional feature), a boolean value specifying whether the `Span` should be `Finish`ed upon being deactivated through its container `Scope` being `Close`d. + Note: This feature is defined as optional, and its existence will depend on its suitability for the thread model, language semantics, API guidelines and other considerations for every given language. -**Returns** a `Scope` instance containing the newly activated `Span`. +**Returns** a `Scope` instance corresponding to the newly activated `Span`. #### Retrieve the active `Span` There should be no parameters. -**Returns** a `Scope` instance containing the active `Span`, or else `null` if there's none for the current thread or execution unit. +**Returns** the active `Span` instance, or else `null` if there's none for the current thread or execution unit. + +#### Retrieve the active `Scope` + +There should be no parameters. + +**Returns** a `Scope` instance corresponding to the active `Span`, or else `null` if there's no active `Span` for the current thread or execution unit. ### `Scope` -The `Scope` interface acts as a simple container for the active `Span`,and it is not guaranteed to be thread-safe. It has the following capabilities: +The `Scope` interface is used to end the active period for a given `Span`,and it is not guaranteed to be thread-safe. It has the following capabilities: -#### Retrieve the contained `Span` +#### Retrieve the `Span` (optional) There should be no parameters. -**Returns** the contained `Span`. The returned value can never be `null`. +**Returns** its corresponding `Span`. The returned value can never be `null`. + +Note: This operation is defined as optional, and its existence will depend on its suitability for the thread model, language semantics, API guidelines and other considerations for every given language. #### Close the `Scope` -Closing the `Scope` will make its contained `Span` stop being the currently active instance for the thread or execution unit, optionally `Finish`ing it depending on the **finish Span on close** parameter that was provided during activation. +Closing the `Scope` will make its corresponding `Span` stop being the currently active instance for the thread or execution unit. -If the `Scope` instance being `Close`d does not correspond to the actually active one, no action will be performed. An additional side effect will be restoring the previously active `Span` instance along with its `Scope` container. +If the `Scope` instance being `Close`d does not correspond to the actually active one, **no action** will be performed. An additional side effect will be restoring the previously active `Span` instance along with its corresponding `Scope` instance. There should be no parameters. +**`Finish`ing the `Span`** is defined as an optional feature. Depending on a **finish Span on close** parameter that might have been provided during activation, its corresponding `Span` will be `Finish`ed. Note: This feature is defined as optional, and its existence will depend on its suitability for the thread model, language semantics, API guidelines and other considerations for every given language. + ### `NoopTracer` All OpenTracing language APIs must also provide some sort of `NoopTracer` implementation which can be used to flag-control OpenTracing or inject something harmless for tests (et cetera). In some cases (for example, Java) the `NoopTracer` may be in its own packaging artifact.