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: router instrumentation #458

Merged
merged 39 commits into from May 19, 2021
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a77c69d
feat: implement first version of router instrumentation
rauno56 Apr 27, 2021
1f423a5
chore: add types for router
rauno56 Apr 29, 2021
f5e88db
chore: stop debugging the behaviour of ritm and instrumentation patcher
rauno56 Apr 29, 2021
347b7f5
refactor: pass layer into _setupSpan instead of individual parts of it
rauno56 May 6, 2021
38311e5
test: test few common cases
rauno56 May 6, 2021
873f7cb
feat: rename HTTP span
rauno56 May 7, 2021
7c2f0e3
test: test disabling
rauno56 May 7, 2021
0e4ecfd
test: remove usage of rootSpan in tests
rauno56 May 7, 2021
147ed6b
fix: use a stable version API in inst implementation
rauno56 May 7, 2021
b82ab4a
fix: fix typo in assertSpans
rauno56 May 7, 2021
97ccf0c
style: fix typing and linting issues
rauno56 May 7, 2021
8572f71
docs: fill in blanks in the readme
rauno56 May 7, 2021
f2b5ce2
docs: add example
rauno56 May 7, 2021
51c6eca
fix: capture exceptions
rauno56 May 7, 2021
98919bb
fix: address linting issues
rauno56 May 7, 2021
9cde95a
style: run eslint with `--ext ts`
rauno56 May 7, 2021
45120b4
fix: fix reference to the instrumentation package in the example
rauno56 May 7, 2021
89f1fca
fix: fix versions
rauno56 May 10, 2021
9ed9c62
style: use optional chaining in tests accessing parentSpan
rauno56 May 10, 2021
131160f
test: fix the test asserting version number
rauno56 May 10, 2021
ffa6735
chore: update api version used in router instrumentation
rauno56 May 10, 2021
3c02476
Merge branch 'main' into feat/router-instrumentation
rauno56 May 12, 2021
df8b51d
docs: capitalize Router in the title
rauno56 May 12, 2021
6a0d5ff
docs: remove references to gitter from router README
rauno56 May 12, 2021
2c4651c
docs: capitalize Router in package.json
rauno56 May 12, 2021
e946ae3
docs: add comments about the if statement in the wrappers
rauno56 May 12, 2021
7d01f72
fix: don't fill version with arbitrary data
rauno56 May 12, 2021
8009cfd
fix: remove the unneeded cast in utils
rauno56 May 12, 2021
b347a7a
docs: remove references to gitter from restify README
rauno56 May 12, 2021
6386c46
Merge branch 'main' into feat/router-instrumentation
rauno56 May 13, 2021
6d1d0e2
style: eslint fix
rauno56 May 13, 2021
b2d2b0a
fix: substitute `<anonymous>` for unnamed function name
rauno56 May 13, 2021
efa99a8
refactor: move enums into `enums/*`
rauno56 May 13, 2021
97d93f0
feat: prefer `??` over `||`
rauno56 May 13, 2021
d311d00
feat: squash with enum change!!
rauno56 May 13, 2021
74da50e
fix: only import Router types in instrumentation
rauno56 May 13, 2021
48c30e7
style: prefer api.diag to destructuring
rauno56 May 13, 2021
7e63ae4
feat: only ever run span.end once
rauno56 May 13, 2021
9e8455e
Merge branch 'main' into feat/router-instrumentation
rauno56 May 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 45 additions & 0 deletions examples/router/README.md
@@ -0,0 +1,45 @@
# Overview

OpenTelemetry Router 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 Router API. All generated spans include following attributes:

- `http.route`: resolved route;
- `router.name`: the name of the handler or middleware;
- `router.type`: either `middleware` or `request_handler`;
- `router.version`: `router` 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
38 changes: 38 additions & 0 deletions examples/router/client.js
@@ -0,0 +1,38 @@
'use strict';

// required to initialize the service name for the auto-instrumentation
require('./tracer')('example-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');
// 404
makeRequest('/bye/world');
// error
makeRequest('/err');
45 changes: 45 additions & 0 deletions examples/router/package.json
@@ -0,0 +1,45 @@
{
"name": "router-example",
"private": true,
"version": "0.16.0",
"description": "Example of router 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",
rauno56 marked this conversation as resolved.
Show resolved Hide resolved
"@opentelemetry/exporter-jaeger": "^0.18.0",
"@opentelemetry/exporter-zipkin": "^0.18.0",
"@opentelemetry/instrumentation": "^0.18.0",
"@opentelemetry/instrumentation-http": "^0.18.0",
"@opentelemetry/instrumentation-router": "^0.16.0",
"@opentelemetry/node": "^0.18.0",
"@opentelemetry/tracing": "^0.18.0",
"router": "^1.3.5"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js#readme",
"devDependencies": {
"cross-env": "^6.0.0"
}
}
46 changes: 46 additions & 0 deletions examples/router/server.js
@@ -0,0 +1,46 @@
'use strict';

require('./tracer')('example-router-server');

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

const http = require('http');
const Router = require('router');

const router = Router();

router.use(setDefaultName);

router.param('name', (req, res, next, name) => {
req.params.name = typeof name === 'string' ? name.toUpperCase() : req.defaultName;
next();
});

// eslint-disable-next-line prefer-arrow-callback
router.get('/hello/:name', function greetingHandler(req, res) {
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.end(`Hello, ${req.params.name}!`);
});

// eslint-disable-next-line prefer-arrow-callback
router.get('/err', function erroringRoute(req, res, next) {
next(new Error('Broken!'));
});

// eslint-disable-next-line prefer-arrow-callback, func-names
const server = http.createServer(function (req, res) {
router(req, res, (error) => {
if (error) {
res.statusCode = 500;
} else {
res.statusCode = 404;
}
res.end();
});
});

server.listen(8080);
50 changes: 50 additions & 0 deletions examples/router/tracer.js
@@ -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 { RouterInstrumentation } = require('@opentelemetry/instrumentation-router');

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,
RouterInstrumentation,
],
});

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('router-example');
};
17 changes: 9 additions & 8 deletions plugins/node/opentelemetry-instrumentation-restify/README.md
@@ -1,6 +1,6 @@
# OpenTelemetry Restify Instrumentation for Node.js

[![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image]
Expand Down Expand Up @@ -46,17 +46,18 @@ See [examples/restify](https://github.com/open-telemetry/opentelemetry-js-contri

- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
- For more about OpenTelemetry JavaScript: <https://github.com/open-telemetry/opentelemetry-js>
- For help or feedback on this project, join us on [gitter][gitter-url]
- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]

## License

Apache 2.0 - See [LICENSE][license-url] for more information.

[gitter-image]: https://badges.gitter.im/open-telemetry/opentelemetry-js.svg
[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions
[license-url]: https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib/status.svg?path=packages/opentelemetry-instrumentation-restify
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=packages%2Fopentelemetry-instrumentation-restify
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib/dev-status.svg?path=packages/opentelemetry-instrumentation-restify
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=packages%2Fopentelemetry-instrumentation-restify&type=dev
[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js-contrib.svg?path=plugins%2Fnode%2Fopentelemetry-instrumentation-restify
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fnode%2Fopentelemetry-instrumentation-restify
[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js-contrib.svg?path=plugins%2Fnode%2Fopentelemetry-instrumentation-restify&type=dev
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fnode%2Fopentelemetry-instrumentation-restify&type=dev
[npm-url]: https://www.npmjs.com/package/@opentelemetry/instrumentation-restify
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Finstrumentation-restify.svg
@@ -0,0 +1 @@
build
@@ -0,0 +1,7 @@
module.exports = {
"env": {
"mocha": true,
"node": true
},
...require('../../../eslint.config.js')
}
@@ -0,0 +1,4 @@
/bin
/coverage
/doc
/test