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: restify instrumentation #416

Merged
merged 31 commits into from
Apr 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0149bcf
feat: initial implementation of restify instrumentation
rauno56 Apr 5, 2021
96f73e6
feat: create spans instead of altering parent spans
rauno56 Apr 6, 2021
4f920f5
feat: clean examples up
rauno56 Apr 6, 2021
92af233
feat: make exporter configurable like other examples
rauno56 Apr 7, 2021
3c37d7f
feat: implement disabling restify instrumentation
rauno56 Apr 8, 2021
32b8931
test: be more verbose in tests and check all spans
rauno56 Apr 8, 2021
ee64e4d
fix: remove the handlers from req, those events seem not to be fired
rauno56 Apr 8, 2021
b6c8318
refactor: export the instrumentation as default
rauno56 Apr 8, 2021
a46adb7
fix: thrown errors are generally not caught in restify
rauno56 Apr 8, 2021
5d67867
feat: enable the instrumentation for all versions after 4.0.0
rauno56 Apr 8, 2021
c4657df
docs: update docs and metadata in package.json and README.md files
rauno56 Apr 8, 2021
cbbdea0
style: fix linting errors
rauno56 Apr 9, 2021
c760527
style: make _moduleVersion optional
rauno56 Apr 12, 2021
4ca8036
feat: use more descriptive span name
rauno56 Apr 13, 2021
e9ab22e
feat: rename HTTP span
rauno56 Apr 13, 2021
0dc22aa
feat: remove creating additional span on the client side
rauno56 Apr 13, 2021
6c380a2
docs: remove TODO
rauno56 Apr 13, 2021
3b8072b
feat: update version
rauno56 Apr 13, 2021
fa55dab
test: test more verbose API
rauno56 Apr 13, 2021
ac8d41b
fix: update version
rauno56 Apr 14, 2021
520d54e
fix: update the example in README
rauno56 Apr 14, 2021
b5be54c
fix: reference @opentelemetry/instrumentation-http correctly
rauno56 Apr 14, 2021
14772ba
feat: remove lodash.once
rauno56 Apr 15, 2021
c8914d1
style: rename constants to be more verbose
rauno56 Apr 15, 2021
88f6052
feat: handle cases with promises
rauno56 Apr 15, 2021
df87efd
feat: support async and promise-returning handlers
rauno56 Apr 15, 2021
4b58434
style: use RestifyInstrumentation as the import name
rauno56 Apr 15, 2021
c4dee5c
feat: let the example be broken until the publish for consistency
rauno56 Apr 15, 2021
f8bcb5c
fix: remove lodash.once types
rauno56 Apr 15, 2021
fd906b1
Merge branch 'main' into feat/restify-instrumentation
vmarchaud Apr 15, 2021
f4f4b08
Merge branch 'main' into feat/restify-instrumentation
rauno56 Apr 16, 2021
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
45 changes: 45 additions & 0 deletions examples/restify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Overview

OpenTelemetry Restify Instrumentation allows the user to automatically collect trace data and export them to the backend of choice (we can use Zipkin or Jaeger for this example). This example demonstrates tracing calls made to Restify API. All generated spans include following attributes:

- `http.route`: resolved route;
- `restify.method`: server method used to register the handler. One of `use`, `pre`, `del`, `get`, `head`, `opts`, `post`, `put` or `patch`;
- `restify.type`: either `middleware` or `request_handler`;
- `restify.version`: `restify` version running.

## Setup

Setup [Zipkin Tracing](https://zipkin.io/pages/quickstart.html)
or
Setup [Jaeger Tracing](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one)

## Run the Application

First install the dependencies:

```sh
npm install
```

### Zipkin

```sh
npm run zipkin:server # Run the server
npm run zipkin:client # Run the client in a separate terminal
```

### Jaeger

```sh
npm run jaeger:server # Run the server
npm run jaeger:client # Run the client in a separate terminal
```

## Useful links

- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
- For more information on OpenTelemetry for Node.js, visit: <https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-node>

## LICENSE

Apache License 2.0
35 changes: 35 additions & 0 deletions examples/restify/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict';

// required to initialize the service name for the auto-instrumentation
require('./tracer')('example-restify-client');
// eslint-disable-next-line import/order
const http = require('http');

/** A function which makes requests and handles response. */
function makeRequest(path) {
// span corresponds to outgoing requests. Here, we have manually created
// the span, which is created to track work that happens outside of the
// request lifecycle entirely.
http.get({
host: 'localhost',
headers: {
accept: 'text/plain',
},
port: 8080,
path,
}, (response) => {
response.on('data', (chunk) => console.log(path, '::', chunk.toString('utf8')));
response.on('end', () => {
console.log(path, 'status', response.statusCode);
});
});

// The process must live for at least the interval past any traces that
// must be exported, or some risk being lost if they are recorded after the
// last export.
console.log('Sleeping 5 seconds before shutdown to ensure all records are flushed.');
setTimeout(() => { console.log('Completed.'); }, 5000);
}

makeRequest('/hello/world');
makeRequest('/bye/world');
Binary file added examples/restify/images/jaeger-ui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/restify/images/zipkin-ui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions examples/restify/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "restify-example",
"private": true,
"version": "0.18.0",
Copy link
Member

Choose a reason for hiding this comment

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

Nit: 0.15.0 in core we have 0.18.x

Copy link
Member

@vmarchaud vmarchaud Apr 16, 2021

Choose a reason for hiding this comment

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

Version in examples are not kept in sync in this repo, i think it would be better to do it with lerna instead

EDit: #428

"description": "Example of restify integration with OpenTelemetry",
"main": "index.js",
"scripts": {
"zipkin:server": "cross-env EXPORTER=zipkin node ./server.js",
"zipkin:client": "cross-env EXPORTER=zipkin node ./client.js",
"jaeger:server": "cross-env EXPORTER=jaeger node ./server.js",
"jaeger:client": "cross-env EXPORTER=jaeger node ./client.js"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/open-telemetry/opentelemetry-js.git"
},
"keywords": [
"opentelemetry",
"http",
"tracing"
],
"engines": {
"node": ">=8"
},
"author": "OpenTelemetry Authors",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/open-telemetry/opentelemetry-js/issues"
},
"dependencies": {
"@opentelemetry/api": "^0.18.0",
"@opentelemetry/exporter-jaeger": "^0.18.0",
"@opentelemetry/exporter-zipkin": "^0.18.0",
"@opentelemetry/instrumentation": "^0.18.0",
"@opentelemetry/instrumentation-http": "^0.18.0",
"@opentelemetry/node": "^0.18.0",
"@opentelemetry/tracing": "^0.18.0",
"restify": "^4.3.4"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js#readme",
"devDependencies": {
"cross-env": "^6.0.0"
}
}
47 changes: 47 additions & 0 deletions examples/restify/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict';

const api = require('@opentelemetry/api');

const { diag, DiagConsoleLogger, DiagLogLevel } = api;
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.VERBOSE);

const restify = require('restify');
require('./tracer')('example-restify-server');

const server = restify.createServer();
const PORT = 8080;

server.pre((req, res, next) => {
next();
});

// `setDefaultName` shows up in spans as the name
const setDefaultName = (req, res, next) => {
req.defaultName = 'Stranger';
next();
};

server.use([(req, res, next) => {
/*
noop to showcase use with an array.
as this is an anonymous fn, the name is not known and cannot be displayed in traces.
*/
next();
}, setDefaultName]);

// named function to be used in traces
// eslint-disable-next-line prefer-arrow-callback
server.get('/hello/:name', function hello(req, res, next) {
console.log('Handling hello');
res.send(`Hello, ${req.params.name || req.defaultName}\n`);
return next();
});

server.get('/bye/:name', (req, res, next) => {
console.log('Handling bye');
return next(new Error('Ooops in bye'));
});

server.listen(PORT, () => {
console.log('Ready on %s', server.url);
});
50 changes: 50 additions & 0 deletions examples/restify/tracer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

const opentelemetry = require('@opentelemetry/api');

const { diag, DiagConsoleLogger, DiagLogLevel } = opentelemetry;
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.VERBOSE);

const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { NodeTracerProvider } = require('@opentelemetry/node');
const { SimpleSpanProcessor, ConsoleSpanExporter } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');

const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const { RestifyInstrumentation } = require('@opentelemetry/instrumentation-restify');

const Exporter = ((exporterParam) => {
if (typeof exporterParam === 'string') {
const exporterString = exporterParam.toLowerCase();
if (exporterString.startsWith('z')) {
return ZipkinExporter;
}
if (exporterString.startsWith('j')) {
return JaegerExporter;
}
}
return ConsoleSpanExporter;
})(process.env.EXPORTER);

module.exports = (serviceName) => {
const provider = new NodeTracerProvider();
registerInstrumentations({
tracerProvider: provider,
instrumentations: [
HttpInstrumentation,
RestifyInstrumentation,
],
});

const exporter = new Exporter({
serviceName,
});

provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

// Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings
provider.register();

return opentelemetry.trace.getTracer('restify-example');
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
"env": {
"mocha": true,
"node": true
},
...require('../../../eslint.config.js')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/bin
/coverage
/doc
/test
Loading