Skip to content
This repository was archived by the owner on Jan 21, 2026. It is now read-only.

feat: ensure spans are non-null#680

Merged
kjin merged 7 commits intogoogleapis:masterfrom
kjin:new-span-data
Mar 16, 2018
Merged

feat: ensure spans are non-null#680
kjin merged 7 commits intogoogleapis:masterfrom
kjin:new-span-data

Conversation

@kjin
Copy link
Copy Markdown
Contributor

@kjin kjin commented Mar 2, 2018

Fixes #656

This PR changes the public API so that spans are never null (in runInRootSpan or createChildSpan). Instead, they now expose a type field which represents whether they are real or "virtual spans". The code docs for SpanDataType in this file should explain the purpose of type.

Open questions:

  1. Is this semver-major?
  2. Does SpanData#type need to have distinct ROOT and CHILD values?

Example

import * as trace from '.';
import { createReadStream } from 'fs';

const traceApi = trace.start();

// original
{
  function doWork(onChunk) {
    const stream = createReadStream('large-file', 'utf8');
    traceApi.runInRootSpan({ name: 'outer' }, rootSpan => {
      if (rootSpan) {
        // only attempt to propagate context if root span isn't null
        traceApi.wrapEmitter(stream);
      }
      let count = 0;
      stream.on('data', onChunk);
      stream.on('end', () => {
        // rootSpan could be null
        if (rootSpan) {
          rootSpan.endSpan();
        }
      });
    });
  }

  doWork((data) => {
    const childSpan = traceApi.createChildSpan({ name: `inner-${count++}` });
    // childSpan could be null
    if (childSpan) {
      childSpan.addLabel('data-length', data.length);
      childSpan.endSpan();
    } else {
      // Why not? Unclear
    }
  });
}

// changed
{
  function doWork(onChunk) {
    const stream = createReadStream('large-file', 'utf8');
    traceApi.runInRootSpan({ name: 'outer' }, rootSpan => {
      if (rootSpan.type === traceApi.spanTypes.ROOT) {
        // only attempt to propagate context if this span is really being traced
        traceApi.wrapEmitter(stream);
      }
      let count = 0;
      stream.on('data', onChunk);
      stream.on('end', () => {
        rootSpan.endSpan();
      });
    });
  }

  doWork((data) => {
    const childSpan = traceApi.createChildSpan({ name: `inner-${count++}` });
    childSpan.addLabel('data-length', data.length);
    childSpan.endSpan();
    // Log if context was lost somehow
    if (childSpan.type === traceApi.spanTypes.UNCORRELATED) {
      console.log('we must have lost context');
    }
  });
}

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Mar 2, 2018
@ofrobots
Copy link
Copy Markdown
Contributor

ofrobots commented Mar 2, 2018

This would be semver major if existing user code must be changed in order to continue working. I haven't reviewed due to the DNR warning at the top, but my suspicion is that this is not semver major.

@kjin
Copy link
Copy Markdown
Contributor Author

kjin commented Mar 2, 2018

@ofrobots I'll add an example of how it changed in the abstract shortly. I also think it's not, but wanted to make sure everyone was on the same page.

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 6, 2018

Codecov Report

Merging #680 into master will decrease coverage by 0.01%.
The diff coverage is 92.85%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #680      +/-   ##
==========================================
- Coverage      90%   89.99%   -0.02%     
==========================================
  Files          30       29       -1     
  Lines        1411     1419       +8     
  Branches      289      288       -1     
==========================================
+ Hits         1270     1277       +7     
- Misses         56       57       +1     
  Partials       85       85
Impacted Files Coverage Δ
src/plugins/plugin-http2.ts 85.45% <0%> (ø) ⬆️
src/plugins/plugin-redis.ts 91.66% <100%> (-0.2%) ⬇️
src/plugins/plugin-restify.ts 96.96% <100%> (ø) ⬆️
src/plugins/plugin-connect.ts 91.89% <100%> (+0.22%) ⬆️
src/constants.ts 100% <100%> (ø) ⬆️
src/plugins/plugin-http.ts 90.24% <100%> (ø) ⬆️
src/trace.ts 100% <100%> (ø) ⬆️
src/plugins/plugin-mysql2.ts 83.78% <100%> (ø) ⬆️
src/plugins/plugin-koa.ts 88.13% <100%> (+0.2%) ⬆️
src/trace-writer.ts 87.69% <100%> (+0.87%) ⬆️
... and 9 more

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 6b8a82b...3803fa9. Read the comment docs.

@kjin kjin force-pushed the new-span-data branch 2 times, most recently from 8d50449 to b23273e Compare March 6, 2018 21:34
Comment thread src/cls.ts

// This is only used in tests (and is temporary), so it doesn't apply in the
// comment in getRootContext about the possible values of namespace.get('root').
// It's functionally identical to setRootContext(null).

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/plugins/plugin-grpc.ts Outdated
// The span name will be of form "grpc:/[Service]/[MethodName]".
var span = api.createChildSpan({ name: 'grpc:' + method.path });
if (!span) {
if (span.type !== api.spanTypes.CHILD) {

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/span-data.ts Outdated
traceUtil.truncate(spanName, Constants.TRACE_SERVICE_SPAN_NAME_LIMIT);
this.span = new TraceSpan(spanName, randomSpanId(), parentSpanId);
trace.spans.push(this.span);
trace: Trace, spanName: string, parentSpanId: string,

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

@kjin kjin requested a review from a team March 6, 2018 23:09
Comment thread src/cls.ts Outdated
readonly span: TraceSpan;
readonly trace: Trace;
readonly type: SpanDataType.ROOT;
}|{

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls.ts

// This is only used in tests (and is temporary), so it doesn't apply in the
// comment in getRootContext about the possible values of namespace.get('root').
// It's functionally identical to setRootContext(null).

This comment was marked as spam.

Comment thread src/plugin-types.ts Outdated
endSpan(): void;
}

// export type SpanData = RootSpanData|ChildSpanData;

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/plugin-types.ts
* @returns The return value of calling fn.
*/
runInRootSpan<T>(options: RootSpanOptions, fn: (span: SpanData|null) => T): T;
runInRootSpan<T>(options: RootSpanOptions, fn: (span: SpanData) => T): T;

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/span-data.ts Outdated
traceUtil.truncate(spanName, Constants.TRACE_SERVICE_SPAN_NAME_LIMIT);
this.span = new TraceSpan(spanName, randomSpanId(), parentSpanId);
trace.spans.push(this.span);
trace: Trace, spanName: string, parentSpanId: string,

This comment was marked as spam.

Comment thread src/span-data.ts Outdated
// tslint:disable-next-line:no-any
addLabel(key: string, value: any) {},
endSpan() {}
} as SpanData & {readonly type: T});

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/span-data.ts Outdated
}

// Helper function to generate static virtual trace spans.
const createDummySpanData =

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/plugins/plugin-grpc.ts Outdated
// The span name will be of form "grpc:/[Service]/[MethodName]".
var span = api.createChildSpan({ name: 'grpc:' + method.path });
if (!span) {
if (span.type !== api.spanTypes.CHILD) {

This comment was marked as spam.

@ofrobots
Copy link
Copy Markdown
Contributor

Note the example you provide in OP

      if (rootSpan.type === traceApi.spanTypes.ROOT) {
        // only attempt to propagate context if this span is really being traced
        traceApi.wrapEmitter(stream);
      }

The test should be self-documenting. Right now you needed a comment to explain what the test is achieving.

@kjin kjin force-pushed the new-span-data branch 4 times, most recently from 8e885e7 to d4f2bfd Compare March 13, 2018 19:51
@kjin
Copy link
Copy Markdown
Contributor Author

kjin commented Mar 14, 2018

@ofrobots PTAL

Comment thread src/cls.ts Outdated
import {Trace, TraceSpan} from './trace';

export type RealRootContext = {
readonly span: TraceSpan; readonly trace: Trace; readonly type: SpanDataType

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/trace.ts
name: string;
spanId: string;
parentSpanId: string;
parentSpanId?: string;

This comment was marked as spam.

This comment was marked as spam.

Copy link
Copy Markdown
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

@kjin
Copy link
Copy Markdown
Contributor Author

kjin commented Mar 16, 2018

Node 4 CI will pass in ~10 min (tests passed, but SSH connection is open)

@kjin kjin merged commit 49b2118 into googleapis:master Mar 16, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

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