Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow "disabling" cls, and relax requirements for creating root spans #728

Merged
merged 11 commits into from
Apr 25, 2018

Conversation

kjin
Copy link
Contributor

@kjin kjin commented Apr 19, 2018

Fixes #719

This PR introduces a new config option clsMechanism that can either be set to 'none' or 'auto' (and defaults to the latter, preserving the current behavior). Setting it to 'none' effectively treats the entire application as sharing the same root context, so any code running subsequent to runInRootSpan(spanConfig, (rootSpan) => { /*...*/ }) will see all child spans created under that root until rootSpan.endSpan() is called.

The 'none' CLS mechanism is at odds with the previous limitation that there may only be one root span per context, so this PR also changes behavior so that when a root span ends, context is cleared. As a result, this code path should now never be executed, so I have removed it.

The new semantics for creating root spans is as follows:

  • If there is no root context in the current continuation, create a new root span, and a corresponding root context in the current continuation.
  • If there is a root context in the current continuation, do not create a new root span.
  • When a root span is ended, clear the root context in the current continuation. (This is the new change)

Note that the "current continuation" in the first and third bullet points may not be the same continuation, even if the root spans mentioned are the same. It is still OK to clear the root context in the current continuation (as stated in the third bullet point) because there was none to begin with.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Apr 19, 2018
@kjin kjin force-pushed the cls-new-4 branch 2 times, most recently from 248e332 to 6693f8a Compare April 19, 2018 18:26
@codecov
Copy link

codecov bot commented Apr 19, 2018

Codecov Report

Merging #728 into master will increase coverage by 0.17%.
The diff coverage is 89.65%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #728      +/-   ##
==========================================
+ Coverage   90.74%   90.92%   +0.17%     
==========================================
  Files          30       30              
  Lines        1556     1564       +8     
  Branches      304      302       -2     
==========================================
+ Hits         1412     1422      +10     
+ Misses         61       59       -2     
  Partials       83       83
Impacted Files Coverage Δ
src/cls/async-listener.ts 100% <ø> (ø) ⬆️
src/config.ts 100% <ø> (ø) ⬆️
src/cls/universal.ts 92.3% <100%> (+15.38%) ⬆️
src/trace-api.ts 94.44% <100%> (+0.06%) ⬆️
src/index.ts 83.72% <83.33%> (+0.38%) ⬆️
src/cls.ts 94.23% <90%> (+0.75%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update edb8135...035b045. Read the comment docs.

@ofrobots
Copy link
Contributor

Is RootSpan synonymous with a Context now?

src/cls.ts Outdated
if (asyncHooksAvailable) {
this.CLSClass = AsyncHooksCLS;
this.rootSpanStackOffset = 4;
break;

This comment was marked as spam.

@@ -69,9 +69,15 @@ export class AsyncListenerCLS<Context extends {}> implements CLS<Context> {
this.getNamespace().set(AsyncListenerCLS.ROOT_CONTEXT_KEY, value);
}

clearContext(): void {
if (this.getContext() !== this.defaultContext) {

This comment was marked as spam.

This comment was marked as spam.

src/config.ts Outdated
/** Available configuration options. */
export interface Config {
/**
* The context propagation mechanism to use. The following options are

This comment was marked as spam.

src/config.ts Outdated
@@ -166,6 +178,7 @@ export interface Config {
* user-provided value will be used to extend the default value.
*/
export const defaultConfig = {
clsMechanism: 'auto' as ContextPropagationMechanism,

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

trace.setPluginLoader();
trace.start();
googleGax = require('./fixtures/google-gax0.16');
});

after(() => {

This comment was marked as spam.

This comment was marked as spam.

src/cls.ts Outdated
this.logger.error(
'TraceCLS#constructor: The specified CLS mechanism',
`[${config.mechanism}] was not recognized.`);
throw new Error(`CLS mechanism [${config.mechanism}] is invalid.`);

This comment was marked as spam.

This comment was marked as spam.

src/cls.ts Outdated
default:
this.logger.error(
'TraceCLS#constructor: The specified CLS mechanism',
`[${config.mechanism}] was not recognized.`);

This comment was marked as spam.

runWithNewContext<T>(fn: Func<T>): T {
return this.getNamespace().runAndReturn(() => {
this.setContext(this.defaultContext);
this.clearContext();

This comment was marked as spam.

This comment was marked as spam.

src/config.ts Outdated
@@ -166,6 +178,7 @@ export interface Config {
* user-provided value will be used to extend the default value.
*/
export const defaultConfig = {
clsMechanism: 'auto' as ContextPropagationMechanism,

This comment was marked as spam.

This comment was marked as spam.

src/index.ts Outdated
@@ -56,6 +56,7 @@ for (let i = 0; i < filesLoadedBeforeTrace.length; i++) {
interface TopLevelConfig {
enabled: boolean;
logLevel: number;
clsMechanism: 'none'|'auto';

This comment was marked as spam.

src/index.ts Outdated
.enable();
const m = config.clsMechanism;
const clsConfig: Forceable<TraceCLSConfig> = {
mechanism: m === 'auto' ? (useAH ? 'async-hooks' : 'async-listener') : m,

This comment was marked as spam.

src/trace-api.ts Outdated
options.name}] because root span [${
rootSpan.span.name}] was already closed.`);
return UNCORRELATED_SPAN;
}

This comment was marked as spam.

This comment was marked as spam.

@kjin
Copy link
Contributor Author

kjin commented Apr 20, 2018

Summary of changes in commit order:

  • I added the TraceCLSMechanism enum. It is not user-facing.
  • Various other changes to address comments.
  • Instead of clearing context, we instead simply explicitly allow root spans to be created when a root span context already exists, but that root span is ended, while still warning if child spans are created under those same conditions. This means that clearContext is now unnecessary and has been removed.

* An enumeration of the possible mechanisms for supporting context propagation
* through continuation-local storage.
*/
export enum TraceCLSMechanism {

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

Copy link
Contributor

@jinwoo jinwoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chatted offline. Using a string enum sounds good to me when their values may come directly from user configs in the future.

LGTM once CI passes.

Copy link
Contributor

@ofrobots ofrobots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm w/ nit.

src/span-data.ts Outdated
@@ -17,6 +17,7 @@
import * as crypto from 'crypto';
import * as util from 'util';

import {cls} from './cls';

This comment was marked as spam.

@kjin kjin merged commit 5d000e9 into googleapis:master Apr 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants