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: make API server to demonstrate distributed tracing #36

Merged
merged 9 commits into from
Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ ENV NODE_ENV=production
ENV ELASTIC_APM_JS_BASE_SERVICE_NAME=opbeans-react
RUN npm install

RUN npm install pm2 -g

COPY --from=opbeans/opbeans-frontend:latest /app/ /app/client/

CMD ["npm", "start"]
CMD ["pm2-runtime"]
Qard marked this conversation as resolved.
Show resolved Hide resolved
64 changes: 64 additions & 0 deletions api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict'

var conf = require('./server/config')
var apmConf = Object.assign({}, conf.apm, {
serviceName: conf.apm.serviceName + '-api'
})
var apm = require('elastic-apm-node').start(apmConf)

// Elastic APM needs to perform an async operation if an uncaught exception
// occurs. This ensures that we close the Express server before this happens to
// we don't keep accepting HTTP requests in the meantime
process.on('uncaughtException', function () {
if (server) server.close()
})

// Ensure the Elastic APM queue is flushed before exiting the application in
// case of an uncaught exception
apm.handleUncaughtExceptions(function (err) {
console.error(err.stack)
console.error('Application encountered an uncaught exception. Flushing Elastic APM queue and exiting...')
apm.flush(function (err) {
if (err) console.error(err.stack)
else console.error('Elastic APM queue flushed!')
process.exit(1)
})
})

var express = require('express')

var app = express()

app.use(function (req, res, next) {
console.log(req.method, req.url, req.headers)
next()
})

app.use(require('body-parser').json())
app.use(function (req, res, next) {
apm.setTag('foo', 'bar')
apm.setTag('lorem', 'ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus, ipsum id scelerisque consequat, enim leo vulputate massa, vel ultricies ante neque ac risus. Curabitur tincidunt vitae sapien id pulvinar. Mauris eu vestibulum tortor. Integer sit amet lorem fringilla, egestas tellus vitae, vulputate purus. Nulla feugiat blandit nunc et semper. Morbi purus libero, mattis sed mauris non, euismod iaculis lacus. Curabitur eleifend ante eros, non faucibus velit lacinia id. Duis posuere libero augue, at dignissim urna consectetur eget. Praesent eu congue est, iaculis finibus augue.')
apm.setTag('this-is-a-very-long-tag-name-without-any-spaces', 'test')
apm.setTag('multi-line', 'foo\nbar\nbaz')

// mimic logged in user
apm.setUserContext({
id: 42,
username: 'kimchy',
email: 'kimchy@elastic.co'
})

// mimic custom context
apm.setCustomContext({
containerId: Math.floor(Math.random() * 10000)
})

next()
})

app.use(require('./server/routes'))

var server = app.listen(conf.server.port2, function () {
var port = server.address().port
console.log('server is listening on port', port)
})
17 changes: 17 additions & 0 deletions ecosystem-workload.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
apps: [{
name: 'workload',
script: './node_modules/.bin/workload',
args: '-f .workload.js',
instances: 1,
restart_delay: 2000
}, {
name: 'server',
script: './server.js',
instances: 1
}, {
name: 'api',
script: './api.js',
instances: 1
}]
}
11 changes: 11 additions & 0 deletions ecosystem.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
apps: [{
name: 'server',
script: './server.js',
instances: 1
}, {
name: 'api',
script: './api.js',
instances: 1
}]
}
18 changes: 17 additions & 1 deletion server.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,23 @@ app.use(function (req, res, next) {
})

app.use(require('./server/coffee'))
app.use('/api', require('./server/routes'))

var http = require('http')
app.use('/api', function (req, res) {
var clientReq = http.request({
method: req.method,
path: req.path.replace(/^\/api/, ''),
hostname: conf.server.hostname,
port: conf.server.port2
})

clientReq.on('response', clientRes => {
clientRes.pipe(res)
})

req.pipe(clientReq)
})

app.get('*', function (req, res) {
res.sendFile(path.resolve(__dirname, 'client/build', 'index.html'))
})
Expand Down
3 changes: 2 additions & 1 deletion server/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ var conf = module.exports = {
protocol: process.env.OPBEANS_SERVER_PROTOCOL || 'http:',
auth: process.env.OPBEANS_SERVER_AUTH || '',
hostname: process.env.OPBEANS_SERVER_HOSTNAME || 'localhost',
port: process.env.OPBEANS_SERVER_PORT || process.env.PORT || 3000
port: process.env.OPBEANS_SERVER_PORT || process.env.PORT || 3000,
port2: process.env.OPBEANS_SERVER_PORT2 || 3001
},
pg: {
database: process.env.PGDATABASE || 'opbeans'
Expand Down