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

Async hooks based context tracking - #538

Merged
matthewloring merged 1 commit into
googleapis:masterfrom
matthewloring:cls
Aug 30, 2017
Merged

matthewloring merged 1 commit into
googleapis:masterfrom
matthewloring:cls

Conversation

@matthewloring

@matthewloring matthewloring commented Aug 10, 2017 •

Copy link
Copy Markdown
Contributor

Introduces a lower overhead, more correct context tracking
mechanism based on async hooks that is available when using the
trace agent on newer versions of node (>=8). To enable async
hooks based context, set the GCLOUD_TRACE_NEW_CONTEXT environment
variable. This change is not expected to have observable behavior
difference but due to the nature of context propagation it is
difficult to say for sure without real world testing.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Aug 10, 2017
@kjin
kjin self-requested a review August 11, 2017 17:14
@matthewloring
matthewloring requested a review from ofrobots August 12, 2017 04:35
@matthewloring

Copy link
Copy Markdown
Contributor Author

I'm still working through the right test plan for this and I'm not sold on the way namespaces are represented in the async hook based implementation but all the high level structure is there and the tests are passing. I would be interested to get some early feedback on this, especially on the required changes to the tests (grpc required the most invasive changes).

Comment thread src/trace-api.js Outdated
var traceId = incomingTraceContext.traceId || (uuid.v4().split('-').join(''));
var parentId = incomingTraceContext.spanId || '0';
var frameOffset;
if (semver.satisfies(process.version, '>=8')) {

This comment was marked as spam.

This comment was marked as spam.

@ofrobots ofrobots left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Still looking.. some initial comments.

Comment thread index.js Outdated
// Load continuation-local-storage first to ensure the core async APIs get
// patched before any user-land modules get loaded.
require('continuation-local-storage');
if (require('semver').satisfies(process.version, '<8')) {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
@@ -0,0 +1,146 @@
/**
* Copyright 2015 Google Inc. All Rights Reserved.

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/trace-api.js Outdated
true, /* Is root span */
options.skipFrames ? options.skipFrames + 2 : 2);
options.skipFrames ?
options.skipFrames + ROOT_SPAN_STACK_OFFSET : ROOT_SPAN_STACK_OFFSET);

This comment was marked as spam.

This comment was marked as spam.

Comment thread test/plugins/common.js
// Monkeypatch the monkeypatcher
var oldIt = global.it;
global.it = function it(title, fn) {
return oldIt.call(this, title, cls.createNamespace().bind(fn));

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
// Core Zone Api

function Context() {
this.properties = {};

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated

Context.prototype.run = function(cb, applyThis, applyArgs) {
const oldContext = current;
current = new Context();

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
}
};

Namespace.prototype.run = function(cb) {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
}
};

Namespace.prototype.runAndReturn = function(cb) {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js
}
};

Namespace.prototype.bind = function(cb) {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
}
};

Namespace.prototype.runAndReturn = function(cb) {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js
}
};

Namespace.prototype.bindEmitter = function(ee) {

This comment was marked as spam.

This comment was marked as spam.

Comment thread test/plugins/common.js
var trace = require('../..');
var cls = require('../../src/cls.js');
if (semver.satisfies(process.version, '>=8')) {
// Monkeypatch the monkeypatcher

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

@matthewloring

Copy link
Copy Markdown
Contributor Author

It looks like appveyor is hanging on hiredis compilation but everything else looks clean. Comments should be addressed. I think this is ready for another look. @kjin @ofrobots

Comment thread .travis.yml

env:
- CXX=g++-4.8
- CXX=g++-4.8 GCLOUD_TRACE_NEW_CONTEXT=1

This comment was marked as spam.

This comment was marked as spam.

Comment thread appveyor.yml Outdated
@@ -25,6 +25,7 @@ install:
- ps: cd ..\..\..\..
# set GCLOUD_PROJECT

This comment was marked as spam.

This comment was marked as spam.

Comment thread index.js
// Load continuation-local-storage first to ensure the core async APIs get
// patched before any user-land modules get loaded.
require('continuation-local-storage');
if (require('semver').satisfies(process.version, '<8') &&

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
return res;
};

Namespace.prototype.runAndReturn = function(fn) {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
}
};

var n = null;

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
const contexts = {};
var current = {};

const hook = asyncHook.createHook({init, before, after, destroy});

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
const asyncHook = require('async_hooks');

const wrappedSymbol = Symbol('context_wrapped');
const contexts = {};

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js

function Namespace() {}

Namespace.prototype.get = function(k) {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
return cb;
}
const boundContext = current;
const wrapped = cb.length === 0 ? function() {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated

Namespace.prototype.bindEmitter = function(ee) {
for (var method of eventEmitterMethods) {
patchEventEmitterMethod(ee, method, this);

This comment was marked as spam.

This comment was marked as spam.

@ofrobots ofrobots left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sorry.. butter fingers

@matthewloring

Copy link
Copy Markdown
Contributor Author

@ofrobots All comments should be addressed. PTAL.

Comment thread src/cls-ah.js Outdated
let contexts = {};
let current = {};

const hook = asyncHook.createHook({init, before, destroy});

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js Outdated
function Namespace() {}

Namespace.prototype.get = function(k) {
return current ? current[k] : undefined;

This comment was marked as spam.

This comment was marked as spam.

@ofrobots ofrobots left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM w/ nits.

Comment thread src/cls-ah.js Outdated
return cb;
}
const boundContext = current;
const wrapped = function contextWrapper() {

This comment was marked as spam.

This comment was marked as spam.

Comment thread src/cls-ah.js
const eventEmitterMethods =
[ 'addListener', 'on', 'once', 'prependListener', 'prependOncelistener' ];

Namespace.prototype.bindEmitter = function(ee) {

This comment was marked as spam.

This comment was marked as spam.

Introduces a lower overhead, more correct context tracking
mechanism based on async hooks that is available when using the
trace agent on newer versions of node (>=8). To enable async
hooks based context, set the GCLOUD_TRACE_NEW_CONTEXT environment
variable. This change is not expected to have observable behavior
difference but due to the nature of context propagation it is
difficult to say for sure without real world testing.
@matthewloring matthewloring changed the title [WIP]: Experiment with async hooks based context tracking Async hooks based context tracking Aug 29, 2017
@matthewloring
matthewloring merged commit 87e4254 into googleapis:master Aug 30, 2017
@matthewloring
matthewloring deleted the cls branch August 30, 2017 02:10
matthewloring added a commit that referenced this pull request Aug 30, 2017
Introduces a lower overhead, more correct context tracking
mechanism based on async hooks that is available when using the
trace agent on newer versions of node (>=8). To enable async
hooks based context, set the GCLOUD_TRACE_NEW_CONTEXT environment
variable. This change is not expected to have observable behavior
difference but due to the nature of context propagation it is
difficult to say for sure without real world testing.

PR-URL: #538
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.

8 participants