SlideShare a Scribd company logo
1 of 84
Download to read offline
Continuation-Local-Storage and 
the Magic of AsyncListener 
Islam Sharabash 
@ibashes 
@DataHero
Agenda 
• Problems caused by the event loop of Node.js 
• Solving problems with AsyncListener API 
• How AsyncListener works
Mo Node Mo Problems 
Things that are hard with the event loop: 
• Having a request ID propagate throughout code 
• Short stack traces from errors in async functions 
• Profiling async functions is painful
Mo Node Mo Problems 
Things that are hard with the event loop: 
• Having a request ID propagate throughout code 
• Short stack traces from errors in async functions 
• Profiling async functions is painful
Propagating Request ID 
(naive)
Propagating Request ID 
(naive) 
var ctx = {rid: uuid.v4()}; 
users.save(ctx, attrs, function(error, userId) { 
users.load(ctx, userId, function(error, user) { 
log.info(‘user created’, 
{rid: ctx.rid, userId: user.id}); 
mailer.sendWelcome(ctx, user, function(error) { 
log.info(‘welcome email sent’, 
{rid: ctx.rid, userId: user.id}); 
}); 
}); 
});
Propagating Request ID 
(naive) 
var ctx = {rid: uuid.v4()}; 
users.save(ctx, attrs, function(error, userId) { 
users.load(ctx, userId, function(error, user) { 
log.info(‘user created’, 
{rid: ctx.rid, userId: user.id}); 
mailer.sendWelcome(ctx, user, function(error) { 
log.info(‘welcome email sent’, 
{rid: ctx.rid, userId: user.id}); 
}); 
}); 
});
Propagating Request ID 
(naive) 
var ctx = {rid: uuid.v4()}; 
users.save(ctx, attrs, function(error, userId) { 
users.load(ctx, userId, function(error, user) { 
log.info(‘user created’, 
{rid: ctx.rid, userId: user.id}); 
mailer.sendWelcome(ctx, user, function(error) { 
log.info(‘welcome email sent’, 
{rid: ctx.rid, userId: user.id}); 
}); 
}); 
});
Mo Node Mo Problems 
Things that are hard with the event loop: 
• Having a request ID propagate throughout code 
• Short stack traces from errors in async functions 
• Profiling async functions is painful
Short Stack Traces 
users.save(attrs, function(error, userId) { 
if (error) { return callback(error); } 
users.load(userId, function(error, user) { 
if (error) { return callback(error); } 
mailers.sendWelcome(user, function(error) { 
if (error) { return callback(error); } 
}); 
}); 
});
Short Stack Traces 
users.save(attrs, function(error, userId) { 
if (error) { return callback(error); } 
users.load(userId, function(error, user) { 
if (error) { return callback(error); } 
mailers.sendWelcome(user, function(error) { 
if (error) { return callback(error); } 
}); 
}); 
});
Short Stack Traces 
Error: ER_PARSE_ERROR You have an error in your SQL syntax... 
at getError (lib/models/database.js:479:24) 
at Query._callback (lib/models/database.js:110:34) 
at Query.Sequence.end (node_modules/mysql/lib/protocol/sequences/Sequence.js:75:24) 
at Query.ErrorPacket (node_modules/mysql/lib/protocol/sequences/Query.js:93:8) 
at Protocol._parsePacket (node_modules/mysql/lib/protocol/Protocol.js:192:24) 
at Parser.write (node_modules/mysql/lib/protocol/Parser.js:62:12) 
at Socket.ondata (stream.js:51:26) 
at Socket.emit (events.js:117:20) 
at Socket. (_stream_readable.js:748:14) 
at Socket.emit (events.js:92:17) 
at emitReadable_ (_stream_readable.js:410:10) 
at emitReadable (_stream_readable.js:406:5) 
at readableAddChunk (_stream_readable.js:168:9) 
at Socket.Readable.push (_stream_readable.js:130:10) 
at TCP.onread (net.js:528:21)
Short Stack Traces 
Error: ER_PARSE_ERROR You have an error in your SQL syntax... 
at getError (lib/models/database.js:479:24) 
at Query._callback (lib/models/database.js:110:34) 
at Query.Sequence.end (node_modules/mysql/lib/protocol/sequences/Sequence.js:75:24) 
at Query.ErrorPacket (node_modules/mysql/lib/protocol/sequences/Query.js:93:8) 
at Protocol._parsePacket (node_modules/mysql/lib/protocol/Protocol.js:192:24) 
at Parser.write (node_modules/mysql/lib/protocol/Parser.js:62:12) 
at Socket.ondata (stream.js:51:26) 
at Socket.emit (events.js:117:20) 
at Socket. (_stream_readable.js:748:14) 
at Socket.emit (events.js:92:17) 
at emitReadable_ (_stream_readable.js:410:10) 
at emitReadable (_stream_readable.js:406:5) 
at readableAddChunk (_stream_readable.js:168:9) 
at Socket.Readable.push (_stream_readable.js:130:10) 
at TCP.onread (net.js:528:21)
Mo Node Mo Problems 
Things that are hard with the event loop: 
• Having a request ID propagate throughout code 
• Short stack traces from errors in async functions 
• Profiling async functions is painful
Profiling Async Functions 
var asyncFunc = function(callback) { 
setTimeout(callback, 1000); 
};
Profiling Async Functions 
var orig = asyncFunc; 
asyncFunc = function() { 
var start = new Date(); 
var args = Array.prototype.slice.call(arguments, 0); 
var cb = args[args.length - 1]; 
args[args.length - 1] = function() { 
console.log((new Date()) - start); 
return cb.apply(this, arguments); 
} 
return orig.apply(this, args); 
}
Profiling Async Functions 
var orig = asyncFunc; 
asyncFunc = function() { 
var start = new Date(); 
var args = Array.prototype.slice.call(arguments, 0); 
var cb = args[args.length - 1]; 
args[args.length - 1] = function() { 
console.log((new Date()) - start); 
return cb.apply(this, arguments); 
} 
return orig.apply(this, args); 
}
Where Do These Problems 
Come From?
Where Do These Problems 
Come From?
Where Do These Problems 
Come From? 
• Asynchronicity and the Event Loop
Where Do These Problems 
Come From? 
• Asynchronicity and the Event Loop 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed
Where Do These Problems 
Come From? 
• Asynchronicity and the Event Loop 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed 
State and stack lost
Where Do These Problems 
Come From? 
• Asynchronicity and the Event Loop 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed 
State and stack lost
How do we solve it? 
• AsyncListener API 
process.createAsyncListener 
process.addAsyncListener 
process.removeAsyncListener 
• Available in Node >0.11.9; Polyfill for Node <= 0.11.8
AsyncListener 
process 
.nextTick(myFunc);
AsyncListener 
process 
.nextTick(myFunc); 
Event Loop
AsyncListener 
process 
.nextTick(myFunc); 
Some time later… 
Event Loop myFunc Executed
AsyncListener 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed myFunc returns 
myFunc errors 
Some time later…
AsyncListener 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed myFunc returns 
myFunc errors 
Some time later… 
Create Callback
AsyncListener 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed myFunc returns 
myFunc errors 
Some time later… 
Create Callback Before Callback
AsyncListener 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed myFunc returns 
myFunc errors 
Some time later… 
Create Callback Before Callback After / Error Callback
Propagate Request IDs 
How do we solve it?
Propagate Request IDs 
How do we solve it? 
• Don’t use AsyncListener Directly
Propagate Request IDs 
How do we solve it? 
• Don’t use AsyncListener Directly 
• Use continuation-local-storage
Propagate Request IDs 
How do we solve it? 
• Don’t use AsyncListener Directly 
• Use continuation-local-storage 
• But what is it?
continuation-local-storage
continuation-local-storage 
async function 1
continuation-local-storage 
Bag Of Holding 
(CLS makes this) async function 1
continuation-local-storage 
Bag Of Holding 
(CLS makes this) async function 1 
async function 2
continuation-local-storage 
Bag Of Holding 
(CLS makes this) async function 1 
async function 2 
async function 3
continuation-local-storage 
Bag Of Holding 
(CLS makes this) 
async function 1 
async function 2 
async function 3 
Each async chain gets it’s own bag
continuation-local-storage 
Bag Of Holding 
(CLS makes this) async function 1 
async function 2 
async function 3 
async function 1 
async function 2 
async function 3 
Each async chain gets it’s own bag
Propagate Request IDs 
Want 
• Request ID in every log message 
• Easy
Propagate Request IDs 
Want 
2013-12-20T18:12:20.037Z - Executing SQL BEGIN statement 
2013-12-20T18:12:20.385Z - Values and label are different datasources 
2013-12-20T18:12:20.530Z - Executing SQL COMMIT statement 
2013-12-20T18:12:20.531Z - Picking filter implementation: DEFAULT
Propagate Request IDs 
Want 
2013-12-20T18:12:20.037Z - Executing SQL BEGIN statement - 
3dd4ee56-e8e3-4270-bda7-90c5ee409782 
2013-12-20T18:12:20.385Z - Values and label are different datasources - 
02671cb7-d22b-4a3e-9bb8-282608999688 
2013-12-20T18:12:20.530Z - Executing SQL COMMIT statement - 
3dd4ee56-e8e3-4270-bda7-90c5ee409782 
2013-12-20T18:12:20.531Z - Picking filter implementation: DEFAULT - 
02671cb7-d22b-4a3e-9bb8-282608999688
Propagate Request IDs 
How? 
• Create continuation-local-storage namespace 
• Middleware to create/assign Request ID 
• Look up Request ID when logging
Propagate Request IDs 
Create namespace
Propagate Request IDs 
Create namespace 
var createNamespace = 
require(‘continuation-local-storage') 
.createNamespace; 
var namespace = createNamespace('com.datahero');
Propagate Request IDs 
Create namespace 
var createNamespace = 
require(‘continuation-local-storage') 
.createNamespace; 
var namespace = createNamespace('com.datahero'); 
Once at top of application
Propagate Request IDs 
Middleware
Propagate Request IDs 
Middleware 
var getNamespace = 
require(‘continuation-local-storage') 
.getNamespace; 
var namespace = getNamespace('com.datahero'), 
uuid = require('node-uuid');
Propagate Request IDs 
Middleware 
var getNamespace = 
require(‘continuation-local-storage') 
.getNamespace; 
var namespace = getNamespace('com.datahero'), 
uuid = require('node-uuid'); 
Just requiring… nothing special
Propagate Request IDs 
Middleware 
app.use(function(req, res, next) { 
var rid = uuid.v4(); 
namespace.bindEmitter(req); 
namespace.bindEmitter(res); 
namespace.run(function() { 
namespace.set(‘rid’, rid); 
next(); 
}); 
});
Propagate Request IDs 
Middleware 
app.use(function(req, res, next) { 
var rid = uuid.v4(); 
namespace.bindEmitter(req); 
namespace.bindEmitter(res); 
namespace.run(function() { 
namespace.set(‘rid’, rid); 
next(); 
}); 
});
Propagate Request IDs 
Middleware 
app.use(function(req, res, next) { 
var rid = uuid.v4(); 
namespace.bindEmitter(req); 
namespace.bindEmitter(res); 
namespace.run(function() { 
namespace.set(‘rid’, rid); 
next(); 
}); 
});
Propagate Request IDs 
Middleware 
app.use(function(req, res, next) { 
var rid = uuid.v4(); 
namespace.bindEmitter(req); 
namespace.bindEmitter(res); 
namespace.run(function() { 
namespace.set(‘rid’, rid); 
next(); 
}); 
});
Propagate Request IDs 
Middleware 
app.use(function(req, res, next) { 
var rid = uuid.v4(); 
namespace.bindEmitter(req); 
namespace.bindEmitter(res); 
namespace.run(function() { 
namespace.set(‘rid’, rid); 
next(); 
}); 
});
Propagate Request IDs 
Logger
Propagate Request IDs 
Logger 
var getNamespace = 
require(‘continuation-local-storage') 
.getNamespace; 
var namespace = getNamespace(‘com.datahero');
Propagate Request IDs 
Logger 
Logger.debug = function(message) { 
console.log( 
(new Date()).toISOString() + ‘ - ‘ + 
message + ‘ - ‘ + 
namespace.get(‘rid') 
); 
};
Propagate Request IDs 
Logger 
Logger.debug = function(message) { 
console.log( 
(new Date()).toISOString() + ‘ - ‘ + 
message + ‘ - ‘ + 
namespace.get(‘rid') 
); 
};
Propagate Request IDs 
Boom!
Short Stack Traces
Short Stack Traces 
setImmediate(function start() { 
process.nextTick(function howDeep() { 
setImmediate(function isTheStack() { 
throw new Error('Oh no!'); 
}); 
}); 
});
Short Stack Traces 
setImmediate(function start() { 
process.nextTick(function howDeep() { 
setImmediate(function isTheStack() { 
throw new Error('Oh no!'); 
}); 
}); 
}); 
Error: Oh no! 
at Object.isTheStack [as _onImmediate] (short-stack.js:4:13) 
at processImmediate [as _immediateCallback] (timers.js:336:15)
Short Stack Traces 
setImmediate(function start() { 
process.nextTick(function howDeep() { 
setImmediate(function isTheStack() { 
throw new Error('Oh no!'); 
}); 
}); 
}); 
Error: Oh no! 
at Object.isTheStack [as _onImmediate] (short-stack.js:4:13) 
at processImmediate [as _immediateCallback] (timers.js:336:15)
Short Stack Traces
Short Stack Traces 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed myFunc returns 
myFunc errors 
Save copy of stack Stitch stack together
Short Stack Traces 
Use stackup 
• https://www.npmjs.org/package/stackup
Short Stack Traces 
Use stackup 
• https://www.npmjs.org/package/stackup 
npm install --save stackup
Short Stack Traces 
Use stackup 
• https://www.npmjs.org/package/stackup 
npm install --save stackup 
require(‘stackup’);
Profiling Async Code
Profiling Async Code 
process 
.nextTick(myFunc); 
Event Loop myFunc Executed myFunc returns 
myFunc errors 
Record Time 
Compute / Record 
Time Difference
Profiling Async Code 
Use async-profile 
• https://www.npmjs.org/package/async-profile
Profiling Async Code 
Use async-profile 
• https://www.npmjs.org/package/async-profile 
npm install --save async-profile
Profiling Async Code 
Use async-profile 
• https://www.npmjs.org/package/async-profile 
var AsyncProfile = 
require('async-profile') 
function () { 
… 
new AsyncProfile(); 
doAsyncWork(); 
}
Summary 
• Problems 
• Can we solve them? Yes we can! 
• Use continuation-local-storage, stackup, and 
async-profile 
• All built on AsyncListener 
• Prepare for more tracing packages
We’re Hiring 
Email me at islam@datahero.com
Islam Sharabash 
@ibashes 
islam@datahero.com
AsyncListener API 
require(‘async-listener’); 
var al = process.createAsyncListener({ 
create: function(data) {}, 
before: function(context, data) {}, 
after: function(context, data) {}, 
error: function(data, error) {} 
}, data) 
process.addAsyncListener(al);
Cause Of Short Stack Traces 
function foo { bar(); } 
function bar { baz(); } 
function baz { 
process.nextTick(bonk); 
}
Cause Of Short Stack Traces 
function foo { bar(); } 
function bar { baz(); } 
function baz { 
process.nextTick(bonk); 
} 
Stack: 
baz 
bar 
foo
Cause Of Short Stack Traces 
function foo { bar(); } 
function bar { baz(); } 
function baz { 
process.nextTick(bonk); 
} 
Stack:
Cause Of Short Stack Traces 
function foo { bar(); } 
function bar { baz(); } 
function baz { 
process.nextTick(bonk); 
} 
Stack: 
— tick — 
bonk

More Related Content

What's hot

왜 쿠버네티스는 systemd로 cgroup을 관리하려고 할까요
왜 쿠버네티스는 systemd로 cgroup을 관리하려고 할까요왜 쿠버네티스는 systemd로 cgroup을 관리하려고 할까요
왜 쿠버네티스는 systemd로 cgroup을 관리하려고 할까요Jo Hoon
 
Presto ベースのマネージドサービス Amazon Athena
Presto ベースのマネージドサービス Amazon AthenaPresto ベースのマネージドサービス Amazon Athena
Presto ベースのマネージドサービス Amazon AthenaAmazon Web Services Japan
 
Amazon Timestream 시계열 데이터 전용 DB 소개 :: 변규현 - AWS Community Day 2019
Amazon Timestream 시계열 데이터 전용 DB 소개 :: 변규현 - AWS Community Day 2019Amazon Timestream 시계열 데이터 전용 DB 소개 :: 변규현 - AWS Community Day 2019
Amazon Timestream 시계열 데이터 전용 DB 소개 :: 변규현 - AWS Community Day 2019AWSKRUG - AWS한국사용자모임
 
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례Jemin Huh
 
Developing for Remote Bamboo Agents, AtlasCamp US 2012
Developing for Remote Bamboo Agents, AtlasCamp US 2012Developing for Remote Bamboo Agents, AtlasCamp US 2012
Developing for Remote Bamboo Agents, AtlasCamp US 2012Atlassian
 
[오픈소스컨설팅]Java Performance Tuning
[오픈소스컨설팅]Java Performance Tuning[오픈소스컨설팅]Java Performance Tuning
[오픈소스컨설팅]Java Performance TuningJi-Woong Choi
 
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교Amazon Web Services Korea
 
서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해중선 곽
 
SmartChat WhatsApp-clone using AWS Amplify AppSync
SmartChat WhatsApp-clone using AWS Amplify AppSyncSmartChat WhatsApp-clone using AWS Amplify AppSync
SmartChat WhatsApp-clone using AWS Amplify AppSyncThanh Nguyen
 
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020Ji-Woong Choi
 
Amazon SNS로 지속적 관리가 가능한 대용량 푸쉬 시스템 구축 여정 - AWS Summit Seoul 2017
Amazon SNS로 지속적 관리가 가능한 대용량 푸쉬 시스템 구축 여정 - AWS Summit Seoul 2017Amazon SNS로 지속적 관리가 가능한 대용량 푸쉬 시스템 구축 여정 - AWS Summit Seoul 2017
Amazon SNS로 지속적 관리가 가능한 대용량 푸쉬 시스템 구축 여정 - AWS Summit Seoul 2017Amazon Web Services Korea
 
AWS Black Belt Online Seminar 2017 Deployment on AWS
AWS Black Belt Online Seminar 2017 Deployment on AWSAWS Black Belt Online Seminar 2017 Deployment on AWS
AWS Black Belt Online Seminar 2017 Deployment on AWSAmazon Web Services Japan
 
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...Tae-Seong Park
 
Amazon Personalize 개인화 추천 모델 만들기::김태수, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon Personalize 개인화 추천 모델 만들기::김태수, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나Amazon Personalize 개인화 추천 모델 만들기::김태수, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon Personalize 개인화 추천 모델 만들기::김태수, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나Amazon Web Services Korea
 
20200826 AWS Black Belt Online Seminar AWS CloudFormation
20200826 AWS Black Belt Online Seminar AWS CloudFormation 20200826 AWS Black Belt Online Seminar AWS CloudFormation
20200826 AWS Black Belt Online Seminar AWS CloudFormation Amazon Web Services Japan
 
Amazon EC2 제대로 사용하기(김상필) - AWS 웨비나 시리즈 2015
Amazon EC2 제대로 사용하기(김상필) - AWS 웨비나 시리즈 2015Amazon EC2 제대로 사용하기(김상필) - AWS 웨비나 시리즈 2015
Amazon EC2 제대로 사용하기(김상필) - AWS 웨비나 시리즈 2015Amazon Web Services Korea
 
ECS to EKS 마이그레이션 경험기 - 유용환(Superb AI) :: AWS Community Day Online 2021
ECS to EKS 마이그레이션 경험기 - 유용환(Superb AI) :: AWS Community Day Online 2021ECS to EKS 마이그레이션 경험기 - 유용환(Superb AI) :: AWS Community Day Online 2021
ECS to EKS 마이그레이션 경험기 - 유용환(Superb AI) :: AWS Community Day Online 2021AWSKRUG - AWS한국사용자모임
 
Use Elastic Beanstalk Blue/Green Deployment to Reduce Downtime & Risk (DEV330...
Use Elastic Beanstalk Blue/Green Deployment to Reduce Downtime & Risk (DEV330...Use Elastic Beanstalk Blue/Green Deployment to Reduce Downtime & Risk (DEV330...
Use Elastic Beanstalk Blue/Green Deployment to Reduce Downtime & Risk (DEV330...Amazon Web Services
 
Knative로 서버리스 워크로드 구현
Knative로 서버리스 워크로드 구현Knative로 서버리스 워크로드 구현
Knative로 서버리스 워크로드 구현Jinwoong Kim
 
AWS로 사용자 천만 명 서비스 만들기 (윤석찬)- 클라우드 태권 2015
AWS로 사용자 천만 명 서비스 만들기 (윤석찬)- 클라우드 태권 2015 AWS로 사용자 천만 명 서비스 만들기 (윤석찬)- 클라우드 태권 2015
AWS로 사용자 천만 명 서비스 만들기 (윤석찬)- 클라우드 태권 2015 Amazon Web Services Korea
 

What's hot (20)

왜 쿠버네티스는 systemd로 cgroup을 관리하려고 할까요
왜 쿠버네티스는 systemd로 cgroup을 관리하려고 할까요왜 쿠버네티스는 systemd로 cgroup을 관리하려고 할까요
왜 쿠버네티스는 systemd로 cgroup을 관리하려고 할까요
 
Presto ベースのマネージドサービス Amazon Athena
Presto ベースのマネージドサービス Amazon AthenaPresto ベースのマネージドサービス Amazon Athena
Presto ベースのマネージドサービス Amazon Athena
 
Amazon Timestream 시계열 데이터 전용 DB 소개 :: 변규현 - AWS Community Day 2019
Amazon Timestream 시계열 데이터 전용 DB 소개 :: 변규현 - AWS Community Day 2019Amazon Timestream 시계열 데이터 전용 DB 소개 :: 변규현 - AWS Community Day 2019
Amazon Timestream 시계열 데이터 전용 DB 소개 :: 변규현 - AWS Community Day 2019
 
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
 
Developing for Remote Bamboo Agents, AtlasCamp US 2012
Developing for Remote Bamboo Agents, AtlasCamp US 2012Developing for Remote Bamboo Agents, AtlasCamp US 2012
Developing for Remote Bamboo Agents, AtlasCamp US 2012
 
[오픈소스컨설팅]Java Performance Tuning
[오픈소스컨설팅]Java Performance Tuning[오픈소스컨설팅]Java Performance Tuning
[오픈소스컨설팅]Java Performance Tuning
 
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
 
서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해
 
SmartChat WhatsApp-clone using AWS Amplify AppSync
SmartChat WhatsApp-clone using AWS Amplify AppSyncSmartChat WhatsApp-clone using AWS Amplify AppSync
SmartChat WhatsApp-clone using AWS Amplify AppSync
 
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
 
Amazon SNS로 지속적 관리가 가능한 대용량 푸쉬 시스템 구축 여정 - AWS Summit Seoul 2017
Amazon SNS로 지속적 관리가 가능한 대용량 푸쉬 시스템 구축 여정 - AWS Summit Seoul 2017Amazon SNS로 지속적 관리가 가능한 대용량 푸쉬 시스템 구축 여정 - AWS Summit Seoul 2017
Amazon SNS로 지속적 관리가 가능한 대용량 푸쉬 시스템 구축 여정 - AWS Summit Seoul 2017
 
AWS Black Belt Online Seminar 2017 Deployment on AWS
AWS Black Belt Online Seminar 2017 Deployment on AWSAWS Black Belt Online Seminar 2017 Deployment on AWS
AWS Black Belt Online Seminar 2017 Deployment on AWS
 
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
 
Amazon Personalize 개인화 추천 모델 만들기::김태수, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon Personalize 개인화 추천 모델 만들기::김태수, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나Amazon Personalize 개인화 추천 모델 만들기::김태수, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon Personalize 개인화 추천 모델 만들기::김태수, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
 
20200826 AWS Black Belt Online Seminar AWS CloudFormation
20200826 AWS Black Belt Online Seminar AWS CloudFormation 20200826 AWS Black Belt Online Seminar AWS CloudFormation
20200826 AWS Black Belt Online Seminar AWS CloudFormation
 
Amazon EC2 제대로 사용하기(김상필) - AWS 웨비나 시리즈 2015
Amazon EC2 제대로 사용하기(김상필) - AWS 웨비나 시리즈 2015Amazon EC2 제대로 사용하기(김상필) - AWS 웨비나 시리즈 2015
Amazon EC2 제대로 사용하기(김상필) - AWS 웨비나 시리즈 2015
 
ECS to EKS 마이그레이션 경험기 - 유용환(Superb AI) :: AWS Community Day Online 2021
ECS to EKS 마이그레이션 경험기 - 유용환(Superb AI) :: AWS Community Day Online 2021ECS to EKS 마이그레이션 경험기 - 유용환(Superb AI) :: AWS Community Day Online 2021
ECS to EKS 마이그레이션 경험기 - 유용환(Superb AI) :: AWS Community Day Online 2021
 
Use Elastic Beanstalk Blue/Green Deployment to Reduce Downtime & Risk (DEV330...
Use Elastic Beanstalk Blue/Green Deployment to Reduce Downtime & Risk (DEV330...Use Elastic Beanstalk Blue/Green Deployment to Reduce Downtime & Risk (DEV330...
Use Elastic Beanstalk Blue/Green Deployment to Reduce Downtime & Risk (DEV330...
 
Knative로 서버리스 워크로드 구현
Knative로 서버리스 워크로드 구현Knative로 서버리스 워크로드 구현
Knative로 서버리스 워크로드 구현
 
AWS로 사용자 천만 명 서비스 만들기 (윤석찬)- 클라우드 태권 2015
AWS로 사용자 천만 명 서비스 만들기 (윤석찬)- 클라우드 태권 2015 AWS로 사용자 천만 명 서비스 만들기 (윤석찬)- 클라우드 태권 2015
AWS로 사용자 천만 명 서비스 만들기 (윤석찬)- 클라우드 태권 2015
 

Similar to Node.js: Continuation-Local-Storage and the Magic of AsyncListener

MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jscacois
 
Live Streaming & Server Sent Events
Live Streaming & Server Sent EventsLive Streaming & Server Sent Events
Live Streaming & Server Sent Eventstkramar
 
540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdfhamzadamani7
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETGianluca Carucci
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsTimur Shemsedinov
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous JavascriptGarrett Welson
 
Sherlock Homepage - A detective story about running large web services - NDC ...
Sherlock Homepage - A detective story about running large web services - NDC ...Sherlock Homepage - A detective story about running large web services - NDC ...
Sherlock Homepage - A detective story about running large web services - NDC ...Maarten Balliauw
 
How "·$% developers defeat the web vulnerability scanners
How "·$% developers defeat the web vulnerability scannersHow "·$% developers defeat the web vulnerability scanners
How "·$% developers defeat the web vulnerability scannersChema Alonso
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch
 
Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Fwdays
 
Sherlock Homepage (Maarten Balliauw)
Sherlock Homepage (Maarten Balliauw)Sherlock Homepage (Maarten Balliauw)
Sherlock Homepage (Maarten Balliauw)Visug
 
Sherlock Homepage - A detective story about running large web services (VISUG...
Sherlock Homepage - A detective story about running large web services (VISUG...Sherlock Homepage - A detective story about running large web services (VISUG...
Sherlock Homepage - A detective story about running large web services (VISUG...Maarten Balliauw
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the wayOleg Podsechin
 
Async servers and clients in Rest.li
Async servers and clients in Rest.liAsync servers and clients in Rest.li
Async servers and clients in Rest.liKaran Parikh
 
Kraken Front-Trends
Kraken Front-TrendsKraken Front-Trends
Kraken Front-TrendsPayPal
 

Similar to Node.js: Continuation-Local-Storage and the Magic of AsyncListener (20)

MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-es
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.js
 
Live Streaming & Server Sent Events
Live Streaming & Server Sent EventsLive Streaming & Server Sent Events
Live Streaming & Server Sent Events
 
540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.js
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
Sherlock Homepage - A detective story about running large web services - NDC ...
Sherlock Homepage - A detective story about running large web services - NDC ...Sherlock Homepage - A detective story about running large web services - NDC ...
Sherlock Homepage - A detective story about running large web services - NDC ...
 
How "·$% developers defeat the web vulnerability scanners
How "·$% developers defeat the web vulnerability scannersHow "·$% developers defeat the web vulnerability scanners
How "·$% developers defeat the web vulnerability scanners
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.js
 
Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"
 
Sherlock Homepage (Maarten Balliauw)
Sherlock Homepage (Maarten Balliauw)Sherlock Homepage (Maarten Balliauw)
Sherlock Homepage (Maarten Balliauw)
 
Sherlock Homepage - A detective story about running large web services (VISUG...
Sherlock Homepage - A detective story about running large web services (VISUG...Sherlock Homepage - A detective story about running large web services (VISUG...
Sherlock Homepage - A detective story about running large web services (VISUG...
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
 
Async servers and clients in Rest.li
Async servers and clients in Rest.liAsync servers and clients in Rest.li
Async servers and clients in Rest.li
 
Kraken Front-Trends
Kraken Front-TrendsKraken Front-Trends
Kraken Front-Trends
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
Node.js
Node.jsNode.js
Node.js
 

Recently uploaded

%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfkalichargn70th171
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 

Recently uploaded (20)

%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 

Node.js: Continuation-Local-Storage and the Magic of AsyncListener

  • 1. Continuation-Local-Storage and the Magic of AsyncListener Islam Sharabash @ibashes @DataHero
  • 2. Agenda • Problems caused by the event loop of Node.js • Solving problems with AsyncListener API • How AsyncListener works
  • 3. Mo Node Mo Problems Things that are hard with the event loop: • Having a request ID propagate throughout code • Short stack traces from errors in async functions • Profiling async functions is painful
  • 4. Mo Node Mo Problems Things that are hard with the event loop: • Having a request ID propagate throughout code • Short stack traces from errors in async functions • Profiling async functions is painful
  • 6. Propagating Request ID (naive) var ctx = {rid: uuid.v4()}; users.save(ctx, attrs, function(error, userId) { users.load(ctx, userId, function(error, user) { log.info(‘user created’, {rid: ctx.rid, userId: user.id}); mailer.sendWelcome(ctx, user, function(error) { log.info(‘welcome email sent’, {rid: ctx.rid, userId: user.id}); }); }); });
  • 7. Propagating Request ID (naive) var ctx = {rid: uuid.v4()}; users.save(ctx, attrs, function(error, userId) { users.load(ctx, userId, function(error, user) { log.info(‘user created’, {rid: ctx.rid, userId: user.id}); mailer.sendWelcome(ctx, user, function(error) { log.info(‘welcome email sent’, {rid: ctx.rid, userId: user.id}); }); }); });
  • 8. Propagating Request ID (naive) var ctx = {rid: uuid.v4()}; users.save(ctx, attrs, function(error, userId) { users.load(ctx, userId, function(error, user) { log.info(‘user created’, {rid: ctx.rid, userId: user.id}); mailer.sendWelcome(ctx, user, function(error) { log.info(‘welcome email sent’, {rid: ctx.rid, userId: user.id}); }); }); });
  • 9. Mo Node Mo Problems Things that are hard with the event loop: • Having a request ID propagate throughout code • Short stack traces from errors in async functions • Profiling async functions is painful
  • 10. Short Stack Traces users.save(attrs, function(error, userId) { if (error) { return callback(error); } users.load(userId, function(error, user) { if (error) { return callback(error); } mailers.sendWelcome(user, function(error) { if (error) { return callback(error); } }); }); });
  • 11. Short Stack Traces users.save(attrs, function(error, userId) { if (error) { return callback(error); } users.load(userId, function(error, user) { if (error) { return callback(error); } mailers.sendWelcome(user, function(error) { if (error) { return callback(error); } }); }); });
  • 12. Short Stack Traces Error: ER_PARSE_ERROR You have an error in your SQL syntax... at getError (lib/models/database.js:479:24) at Query._callback (lib/models/database.js:110:34) at Query.Sequence.end (node_modules/mysql/lib/protocol/sequences/Sequence.js:75:24) at Query.ErrorPacket (node_modules/mysql/lib/protocol/sequences/Query.js:93:8) at Protocol._parsePacket (node_modules/mysql/lib/protocol/Protocol.js:192:24) at Parser.write (node_modules/mysql/lib/protocol/Parser.js:62:12) at Socket.ondata (stream.js:51:26) at Socket.emit (events.js:117:20) at Socket. (_stream_readable.js:748:14) at Socket.emit (events.js:92:17) at emitReadable_ (_stream_readable.js:410:10) at emitReadable (_stream_readable.js:406:5) at readableAddChunk (_stream_readable.js:168:9) at Socket.Readable.push (_stream_readable.js:130:10) at TCP.onread (net.js:528:21)
  • 13. Short Stack Traces Error: ER_PARSE_ERROR You have an error in your SQL syntax... at getError (lib/models/database.js:479:24) at Query._callback (lib/models/database.js:110:34) at Query.Sequence.end (node_modules/mysql/lib/protocol/sequences/Sequence.js:75:24) at Query.ErrorPacket (node_modules/mysql/lib/protocol/sequences/Query.js:93:8) at Protocol._parsePacket (node_modules/mysql/lib/protocol/Protocol.js:192:24) at Parser.write (node_modules/mysql/lib/protocol/Parser.js:62:12) at Socket.ondata (stream.js:51:26) at Socket.emit (events.js:117:20) at Socket. (_stream_readable.js:748:14) at Socket.emit (events.js:92:17) at emitReadable_ (_stream_readable.js:410:10) at emitReadable (_stream_readable.js:406:5) at readableAddChunk (_stream_readable.js:168:9) at Socket.Readable.push (_stream_readable.js:130:10) at TCP.onread (net.js:528:21)
  • 14. Mo Node Mo Problems Things that are hard with the event loop: • Having a request ID propagate throughout code • Short stack traces from errors in async functions • Profiling async functions is painful
  • 15. Profiling Async Functions var asyncFunc = function(callback) { setTimeout(callback, 1000); };
  • 16. Profiling Async Functions var orig = asyncFunc; asyncFunc = function() { var start = new Date(); var args = Array.prototype.slice.call(arguments, 0); var cb = args[args.length - 1]; args[args.length - 1] = function() { console.log((new Date()) - start); return cb.apply(this, arguments); } return orig.apply(this, args); }
  • 17. Profiling Async Functions var orig = asyncFunc; asyncFunc = function() { var start = new Date(); var args = Array.prototype.slice.call(arguments, 0); var cb = args[args.length - 1]; args[args.length - 1] = function() { console.log((new Date()) - start); return cb.apply(this, arguments); } return orig.apply(this, args); }
  • 18. Where Do These Problems Come From?
  • 19. Where Do These Problems Come From?
  • 20. Where Do These Problems Come From? • Asynchronicity and the Event Loop
  • 21. Where Do These Problems Come From? • Asynchronicity and the Event Loop process .nextTick(myFunc); Event Loop myFunc Executed
  • 22. Where Do These Problems Come From? • Asynchronicity and the Event Loop process .nextTick(myFunc); Event Loop myFunc Executed State and stack lost
  • 23. Where Do These Problems Come From? • Asynchronicity and the Event Loop process .nextTick(myFunc); Event Loop myFunc Executed State and stack lost
  • 24. How do we solve it? • AsyncListener API process.createAsyncListener process.addAsyncListener process.removeAsyncListener • Available in Node >0.11.9; Polyfill for Node <= 0.11.8
  • 27. AsyncListener process .nextTick(myFunc); Some time later… Event Loop myFunc Executed
  • 28. AsyncListener process .nextTick(myFunc); Event Loop myFunc Executed myFunc returns myFunc errors Some time later…
  • 29. AsyncListener process .nextTick(myFunc); Event Loop myFunc Executed myFunc returns myFunc errors Some time later… Create Callback
  • 30. AsyncListener process .nextTick(myFunc); Event Loop myFunc Executed myFunc returns myFunc errors Some time later… Create Callback Before Callback
  • 31. AsyncListener process .nextTick(myFunc); Event Loop myFunc Executed myFunc returns myFunc errors Some time later… Create Callback Before Callback After / Error Callback
  • 32. Propagate Request IDs How do we solve it?
  • 33. Propagate Request IDs How do we solve it? • Don’t use AsyncListener Directly
  • 34. Propagate Request IDs How do we solve it? • Don’t use AsyncListener Directly • Use continuation-local-storage
  • 35. Propagate Request IDs How do we solve it? • Don’t use AsyncListener Directly • Use continuation-local-storage • But what is it?
  • 38. continuation-local-storage Bag Of Holding (CLS makes this) async function 1
  • 39. continuation-local-storage Bag Of Holding (CLS makes this) async function 1 async function 2
  • 40. continuation-local-storage Bag Of Holding (CLS makes this) async function 1 async function 2 async function 3
  • 41. continuation-local-storage Bag Of Holding (CLS makes this) async function 1 async function 2 async function 3 Each async chain gets it’s own bag
  • 42. continuation-local-storage Bag Of Holding (CLS makes this) async function 1 async function 2 async function 3 async function 1 async function 2 async function 3 Each async chain gets it’s own bag
  • 43. Propagate Request IDs Want • Request ID in every log message • Easy
  • 44. Propagate Request IDs Want 2013-12-20T18:12:20.037Z - Executing SQL BEGIN statement 2013-12-20T18:12:20.385Z - Values and label are different datasources 2013-12-20T18:12:20.530Z - Executing SQL COMMIT statement 2013-12-20T18:12:20.531Z - Picking filter implementation: DEFAULT
  • 45. Propagate Request IDs Want 2013-12-20T18:12:20.037Z - Executing SQL BEGIN statement - 3dd4ee56-e8e3-4270-bda7-90c5ee409782 2013-12-20T18:12:20.385Z - Values and label are different datasources - 02671cb7-d22b-4a3e-9bb8-282608999688 2013-12-20T18:12:20.530Z - Executing SQL COMMIT statement - 3dd4ee56-e8e3-4270-bda7-90c5ee409782 2013-12-20T18:12:20.531Z - Picking filter implementation: DEFAULT - 02671cb7-d22b-4a3e-9bb8-282608999688
  • 46. Propagate Request IDs How? • Create continuation-local-storage namespace • Middleware to create/assign Request ID • Look up Request ID when logging
  • 47. Propagate Request IDs Create namespace
  • 48. Propagate Request IDs Create namespace var createNamespace = require(‘continuation-local-storage') .createNamespace; var namespace = createNamespace('com.datahero');
  • 49. Propagate Request IDs Create namespace var createNamespace = require(‘continuation-local-storage') .createNamespace; var namespace = createNamespace('com.datahero'); Once at top of application
  • 50. Propagate Request IDs Middleware
  • 51. Propagate Request IDs Middleware var getNamespace = require(‘continuation-local-storage') .getNamespace; var namespace = getNamespace('com.datahero'), uuid = require('node-uuid');
  • 52. Propagate Request IDs Middleware var getNamespace = require(‘continuation-local-storage') .getNamespace; var namespace = getNamespace('com.datahero'), uuid = require('node-uuid'); Just requiring… nothing special
  • 53. Propagate Request IDs Middleware app.use(function(req, res, next) { var rid = uuid.v4(); namespace.bindEmitter(req); namespace.bindEmitter(res); namespace.run(function() { namespace.set(‘rid’, rid); next(); }); });
  • 54. Propagate Request IDs Middleware app.use(function(req, res, next) { var rid = uuid.v4(); namespace.bindEmitter(req); namespace.bindEmitter(res); namespace.run(function() { namespace.set(‘rid’, rid); next(); }); });
  • 55. Propagate Request IDs Middleware app.use(function(req, res, next) { var rid = uuid.v4(); namespace.bindEmitter(req); namespace.bindEmitter(res); namespace.run(function() { namespace.set(‘rid’, rid); next(); }); });
  • 56. Propagate Request IDs Middleware app.use(function(req, res, next) { var rid = uuid.v4(); namespace.bindEmitter(req); namespace.bindEmitter(res); namespace.run(function() { namespace.set(‘rid’, rid); next(); }); });
  • 57. Propagate Request IDs Middleware app.use(function(req, res, next) { var rid = uuid.v4(); namespace.bindEmitter(req); namespace.bindEmitter(res); namespace.run(function() { namespace.set(‘rid’, rid); next(); }); });
  • 59. Propagate Request IDs Logger var getNamespace = require(‘continuation-local-storage') .getNamespace; var namespace = getNamespace(‘com.datahero');
  • 60. Propagate Request IDs Logger Logger.debug = function(message) { console.log( (new Date()).toISOString() + ‘ - ‘ + message + ‘ - ‘ + namespace.get(‘rid') ); };
  • 61. Propagate Request IDs Logger Logger.debug = function(message) { console.log( (new Date()).toISOString() + ‘ - ‘ + message + ‘ - ‘ + namespace.get(‘rid') ); };
  • 64. Short Stack Traces setImmediate(function start() { process.nextTick(function howDeep() { setImmediate(function isTheStack() { throw new Error('Oh no!'); }); }); });
  • 65. Short Stack Traces setImmediate(function start() { process.nextTick(function howDeep() { setImmediate(function isTheStack() { throw new Error('Oh no!'); }); }); }); Error: Oh no! at Object.isTheStack [as _onImmediate] (short-stack.js:4:13) at processImmediate [as _immediateCallback] (timers.js:336:15)
  • 66. Short Stack Traces setImmediate(function start() { process.nextTick(function howDeep() { setImmediate(function isTheStack() { throw new Error('Oh no!'); }); }); }); Error: Oh no! at Object.isTheStack [as _onImmediate] (short-stack.js:4:13) at processImmediate [as _immediateCallback] (timers.js:336:15)
  • 68. Short Stack Traces process .nextTick(myFunc); Event Loop myFunc Executed myFunc returns myFunc errors Save copy of stack Stitch stack together
  • 69. Short Stack Traces Use stackup • https://www.npmjs.org/package/stackup
  • 70. Short Stack Traces Use stackup • https://www.npmjs.org/package/stackup npm install --save stackup
  • 71. Short Stack Traces Use stackup • https://www.npmjs.org/package/stackup npm install --save stackup require(‘stackup’);
  • 73. Profiling Async Code process .nextTick(myFunc); Event Loop myFunc Executed myFunc returns myFunc errors Record Time Compute / Record Time Difference
  • 74. Profiling Async Code Use async-profile • https://www.npmjs.org/package/async-profile
  • 75. Profiling Async Code Use async-profile • https://www.npmjs.org/package/async-profile npm install --save async-profile
  • 76. Profiling Async Code Use async-profile • https://www.npmjs.org/package/async-profile var AsyncProfile = require('async-profile') function () { … new AsyncProfile(); doAsyncWork(); }
  • 77. Summary • Problems • Can we solve them? Yes we can! • Use continuation-local-storage, stackup, and async-profile • All built on AsyncListener • Prepare for more tracing packages
  • 78. We’re Hiring Email me at islam@datahero.com
  • 79. Islam Sharabash @ibashes islam@datahero.com
  • 80. AsyncListener API require(‘async-listener’); var al = process.createAsyncListener({ create: function(data) {}, before: function(context, data) {}, after: function(context, data) {}, error: function(data, error) {} }, data) process.addAsyncListener(al);
  • 81. Cause Of Short Stack Traces function foo { bar(); } function bar { baz(); } function baz { process.nextTick(bonk); }
  • 82. Cause Of Short Stack Traces function foo { bar(); } function bar { baz(); } function baz { process.nextTick(bonk); } Stack: baz bar foo
  • 83. Cause Of Short Stack Traces function foo { bar(); } function bar { baz(); } function baz { process.nextTick(bonk); } Stack:
  • 84. Cause Of Short Stack Traces function foo { bar(); } function bar { baz(); } function baz { process.nextTick(bonk); } Stack: — tick — bonk