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: replacing base plugin with instrumentation for xml-http-request #1659

Merged
merged 3 commits into from
Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ cache_2: &cache_2
- packages/opentelemetry-plugin-http/node_modules
- packages/opentelemetry-plugin-https/node_modules
- packages/opentelemetry-exporter-collector/node_modules
- packages/opentelemetry-plugin-xml-http-request/node_modules
- packages/opentelemetry-instrumentation-xml-http-request/node_modules
- packages/opentelemetry-resource-detector-aws/node_modules
- packages/opentelemetry-resource-detector-gcp/node_modules
- packages/opentelemetry-resources/node_modules
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ These plugins are hosted at <https://github.com/open-telemetry/opentelemetry-js-

##### Core

- [@opentelemetry/plugin-xml-http-request][otel-plugin-xml-http-request]
- [@opentelemetry/instrumentation-xml-http-request][otel-instrumentation-xml-http-request]
- [@opentelemetry/plugin-fetch][otel-plugin-fetch]

##### Contrib
Expand Down Expand Up @@ -248,7 +248,7 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[otel-plugin-grpc-js]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-grpc-js
[otel-plugin-http]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-http
[otel-plugin-https]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-https
[otel-plugin-xml-http-request]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-xml-http-request
[otel-instrumentation-xml-http-request]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-instrumentation-xml-http-request

[otel-shim-opentracing]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-shim-opentracing
[otel-tracing]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-tracing
Expand Down
2 changes: 1 addition & 1 deletion examples/tracer-web/examples/user-interaction/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</head>

<body>
Example of using Web Tracer with UserInteractionPlugin and XMLHttpRequestPlugin with console exporter and collector exporter
Example of using Web Tracer with UserInteractionPlugin and XMLHttpRequestInstrumentation with console exporter and collector exporter
<script type="text/javascript" src="user-interaction.js"></script>
<br/>
<button id="btnAdd" class="btnAddClass">Add button</button>
Expand Down
4 changes: 2 additions & 2 deletions examples/tracer-web/examples/user-interaction/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { UserInteractionPlugin } from '@opentelemetry/plugin-user-interaction';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import { CollectorTraceExporter } from '@opentelemetry/exporter-collector';
import { B3Propagator } from '@opentelemetry/propagator-b3';
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';

const providerWithZone = new WebTracerProvider({
plugins: [
new UserInteractionPlugin(),
new XMLHttpRequestPlugin({
new XMLHttpRequestInstrumentation({
ignoreUrls: [/localhost/],
propagateTraceHeaderCorsUrls: [
'http://localhost:8090',
Expand Down
4 changes: 2 additions & 2 deletions examples/tracer-web/examples/xml-http-request/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import { CollectorTraceExporter } from '@opentelemetry/exporter-collector';
import { B3Propagator } from '@opentelemetry/propagator-b3';

const providerWithZone = new WebTracerProvider({
plugins: [
new XMLHttpRequestPlugin({
new XMLHttpRequestInstrumentation({
ignoreUrls: [/localhost:8090\/sockjs-node/],
propagateTraceHeaderCorsUrls: [
'https://httpbin.org/get',
Expand Down
2 changes: 1 addition & 1 deletion examples/tracer-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"@opentelemetry/plugin-document-load": "^0.9.0",
"@opentelemetry/plugin-fetch": "^0.12.0",
"@opentelemetry/plugin-user-interaction": "^0.9.0",
"@opentelemetry/plugin-xml-http-request": "^0.12.0",
"@opentelemetry/instrumentation-xml-http-request": "^0.12.0",
"@opentelemetry/tracing": "^0.12.0",
"@opentelemetry/web": "^0.12.0"
},
Expand Down
4 changes: 2 additions & 2 deletions metapackages/plugins-web-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This package depends on all core web plugins maintained by OpenTelemetry authors

## Plugins

- [@opentelemetry/plugin-xml-http-request][otel-plugin-xml-http-request]
- [@opentelemetry/instrumentation-xml-http-request][otel-instrumentation-xml-http-request]

## Useful links

Expand All @@ -30,4 +30,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[npm-url]: https://www.npmjs.com/package/@opentelemetry/plugins-web-core
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fplugins-web-core.svg

[otel-plugin-xml-http-request]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-xml-http-request
[otel-instrumentation-xml-http-request]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-instrumentation-xml-http-request
2 changes: 1 addition & 1 deletion metapackages/plugins-web-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"url": "https://github.com/open-telemetry/opentelemetry-js/issues"
},
"dependencies": {
"@opentelemetry/plugin-xml-http-request": "^0.12.0"
"@opentelemetry/instrumentation-xml-http-request": "^0.12.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,38 @@ This module provides auto instrumentation for web using XMLHttpRequest .
## Installation

```bash
npm install --save @opentelemetry/plugin-xml-http-request
npm install --save @opentelemetry/instrumentation-xml-http-request
```

## Usage

```js
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracer } from '@opentelemetry/web';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
import { ZoneContextManager } from '@opentelemetry/context-zone';

// this is still possible
const webTracerWithZone = new WebTracer({
contextManager: new ZoneContextManager(),
plugins: [
new XMLHttpRequestPlugin({
new XMLHttpRequestInstrumentation({
propagateTraceHeaderCorsUrls: ['http://localhost:8090']
})
]
});
/////////////////////////////////////////

// or plugin can be also initialised separately and then set the tracer provider or meter provider
const xmlHttpRequestInstrumentation = new XMLHttpRequestInstrumentation({
propagateTraceHeaderCorsUrls: ['http://localhost:8090']
});
const webTracerWithZone = new WebTracer({
contextManager: new ZoneContextManager(),
});
xmlHttpRequestInstrumentation.setTracerProvider(webTracerWithZone);
/////////////////////////////////////////

webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));

// and some test
Expand Down Expand Up @@ -61,9 +74,9 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/master/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/status.svg?path=packages/opentelemetry-plugin-xml-http-request
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-plugin-xml-http-request
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-plugin-xml-http-request
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-plugin-xml-http-request&type=dev
[npm-url]: https://www.npmjs.com/package/@opentelemetry/plugin-xml-http-request
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fplugin-xml-http-request.svg
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-instrumentation-xml-http-request
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-instrumentation-xml-http-request
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-instrumentation-xml-http-request
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-instrumentation-xml-http-request&type=dev
[npm-url]: https://www.npmjs.com/package/@opentelemetry/instrumentation-xml-http-request
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Finstrumentation-xml-http-request.svg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@opentelemetry/plugin-xml-http-request",
"name": "@opentelemetry/instrumentation-xml-http-request",
"version": "0.12.0",
"description": "OpenTelemetry XMLHttpRequest automatic instrumentation package.",
"main": "build/src/index.js",
Expand Down Expand Up @@ -50,7 +50,6 @@
"@opentelemetry/tracing": "^0.12.0",
"@types/mocha": "8.0.2",
"@types/node": "14.0.27",
"@types/shimmer": "1.0.1",
"@types/sinon": "9.0.4",
"@types/webpack-env": "1.15.2",
"babel-loader": "8.1.0",
Expand All @@ -77,9 +76,9 @@
},
"dependencies": {
"@opentelemetry/api": "^0.12.0",
"@opentelemetry/instrumentation": "^0.12.0",
"@opentelemetry/core": "^0.12.0",
"@opentelemetry/semantic-conventions": "^0.12.0",
"@opentelemetry/web": "^0.12.0",
"shimmer": "^1.2.1"
"@opentelemetry/web": "^0.12.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@

import * as api from '@opentelemetry/api';
import {
BasePlugin,
hrTime,
isUrlIgnored,
isWrapped,
otperformance,
} from '@opentelemetry/core';
InstrumentationBase,
InstrumentationConfig,
} from '@opentelemetry/instrumentation';
import { hrTime, isUrlIgnored, otperformance } from '@opentelemetry/core';
import { HttpAttribute } from '@opentelemetry/semantic-conventions';
import {
addSpanNetworkEvents,
Expand All @@ -30,7 +29,6 @@ import {
PerformanceTimingNames as PTN,
shouldPropagateTraceHeaders,
} from '@opentelemetry/web';
import * as shimmer from 'shimmer';
import { EventNames } from './enums/EventNames';
import {
OpenFunction,
Expand All @@ -49,7 +47,8 @@ const OBSERVER_WAIT_TIME_MS = 300;
/**
* XMLHttpRequest config
*/
export interface XMLHttpRequestPluginConfig extends api.PluginConfig {
export interface XMLHttpRequestInstrumentationConfig
extends InstrumentationConfig {
// the number of timing resources is limited, after the limit
// (chrome 250, safari 150) the information is not collected anymore
// the only way to prevent that is to regularly clean the resources
Expand All @@ -58,12 +57,20 @@ export interface XMLHttpRequestPluginConfig extends api.PluginConfig {
clearTimingResources?: boolean;
// urls which should include trace headers when origin doesn't match
propagateTraceHeaderCorsUrls?: PropagateTraceHeaderCorsUrls;
/**
* URLs that partially match any regex in ignoreUrls will not be traced.
* In addition, URLs that are _exact matches_ of strings in ignoreUrls will
* also not be traced.
*/
ignoreUrls?: Array<string | RegExp>;
}

/**
* This class represents a XMLHttpRequest plugin for auto instrumentation
*/
export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
export class XMLHttpRequestInstrumentation extends InstrumentationBase<
XMLHttpRequest
> {
readonly component: string = 'xml-http-request';
readonly version: string = VERSION;
moduleName = this.component;
Expand All @@ -72,8 +79,20 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
private _xhrMem = new WeakMap<XMLHttpRequest, XhrMem>();
private _usedResources = new WeakSet<PerformanceResourceTiming>();

constructor(protected _config: XMLHttpRequestPluginConfig = {}) {
super('@opentelemetry/plugin-xml-http-request', VERSION);
constructor(
config: XMLHttpRequestInstrumentationConfig & InstrumentationConfig = {}
) {
super(
'@opentelemetry/instrumentation-xml-http-request',
VERSION,
Object.assign({}, config)
);
}

init() {}

private _getConfig(): XMLHttpRequestInstrumentationConfig {
return this._config;
}

/**
Expand All @@ -86,7 +105,7 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
if (
!shouldPropagateTraceHeaders(
spanUrl,
this._config.propagateTraceHeaderCorsUrls
this._getConfig().propagateTraceHeaderCorsUrls
)
) {
return;
Expand All @@ -108,8 +127,8 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
span: api.Span,
corsPreFlightRequest: PerformanceResourceTiming
): void {
this._tracer.withSpan(span, () => {
const childSpan = this._tracer.startSpan('CORS Preflight', {
this.tracer.withSpan(span, () => {
const childSpan = this.tracer.startSpan('CORS Preflight', {
startTime: corsPreFlightRequest[PTN.FETCH_START],
});
addSpanNetworkEvents(childSpan, corsPreFlightRequest);
Expand Down Expand Up @@ -177,12 +196,12 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {

/**
* Clears the resource timings and all resources assigned with spans
* when {@link XMLHttpRequestPluginConfig.clearTimingResources} is
* when {@link XMLHttpRequestInstrumentationConfig.clearTimingResources} is
* set to true (default false)
* @private
*/
private _clearResources() {
if (this._tasksCount === 0 && this._config.clearTimingResources) {
if (this._tasksCount === 0 && this._getConfig().clearTimingResources) {
((otperformance as unknown) as Performance).clearResourceTimings();
this._xhrMem = new WeakMap<XMLHttpRequest, XhrMem>();
this._usedResources = new WeakSet<PerformanceResourceTiming>();
Expand Down Expand Up @@ -268,13 +287,13 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
url: string,
method: string
): api.Span | undefined {
if (isUrlIgnored(url, this._config.ignoreUrls)) {
if (isUrlIgnored(url, this._getConfig().ignoreUrls)) {
this._logger.debug('ignoring span as url matches ignored url');
return;
}
const spanName = `HTTP ${method.toUpperCase()}`;

const currentSpan = this._tracer.startSpan(spanName, {
const currentSpan = this.tracer.startSpan(spanName, {
kind: api.SpanKind.CLIENT,
attributes: {
[HttpAttribute.HTTP_METHOD]: method,
Expand Down Expand Up @@ -417,7 +436,7 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
const spanUrl = xhrMem.spanUrl;

if (currentSpan && spanUrl) {
plugin._tracer.withSpan(currentSpan, () => {
plugin.tracer.withSpan(currentSpan, () => {
plugin._tasksCount++;
xhrMem.sendStartTime = hrTime();
currentSpan.addEvent(EventNames.METHOD_SEND);
Expand All @@ -443,35 +462,33 @@ export class XMLHttpRequestPlugin extends BasePlugin<XMLHttpRequest> {
}

/**
* implements patch function
* implements enable function
*/
protected patch() {
enable() {
this._logger.debug('applying patch to', this.moduleName, this.version);

if (isWrapped(XMLHttpRequest.prototype.open)) {
shimmer.unwrap(XMLHttpRequest.prototype, 'open');
this._unwrap(XMLHttpRequest.prototype, 'open');
this._logger.debug('removing previous patch from method open');
}

if (isWrapped(XMLHttpRequest.prototype.send)) {
shimmer.unwrap(XMLHttpRequest.prototype, 'send');
this._unwrap(XMLHttpRequest.prototype, 'send');
this._logger.debug('removing previous patch from method send');
}

shimmer.wrap(XMLHttpRequest.prototype, 'open', this._patchOpen());
shimmer.wrap(XMLHttpRequest.prototype, 'send', this._patchSend());

return this._moduleExports;
this._wrap(XMLHttpRequest.prototype, 'open', this._patchOpen());
this._wrap(XMLHttpRequest.prototype, 'send', this._patchSend());
}

/**
* implements unpatch function
* implements disable function
*/
protected unpatch() {
disable() {
this._logger.debug('removing patch from', this.moduleName, this.version);

shimmer.unwrap(XMLHttpRequest.prototype, 'open');
shimmer.unwrap(XMLHttpRequest.prototype, 'send');
this._unwrap(XMLHttpRequest.prototype, 'open');
this._unwrap(XMLHttpRequest.prototype, 'send');

this._tasksCount = 0;
this._xhrMem = new WeakMap<XMLHttpRequest, XhrMem>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Span } from '@opentelemetry/api';
import { HttpAttribute } from '@opentelemetry/semantic-conventions';
import { ReadableSpan, SpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import { XMLHttpRequestPlugin } from '../src';
import { XMLHttpRequestInstrumentation } from '../src';
import assert = require('assert');

class TestSpanProcessor implements SpanProcessor {
Expand All @@ -41,7 +41,7 @@ describe('unmocked xhr', () => {
let provider: WebTracerProvider;
beforeEach(() => {
provider = new WebTracerProvider({
plugins: [new XMLHttpRequestPlugin()],
plugins: [new XMLHttpRequestInstrumentation()],
});
testSpans = new TestSpanProcessor();
provider.addSpanProcessor(testSpans);
Expand Down
Loading