Skip to content
This repository has been archived by the owner on Oct 3, 2023. It is now read-only.

Custom spans #141

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 19 additions & 4 deletions examples/user_interaction/client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* gRPC://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
Expand All @@ -15,6 +15,7 @@
*/

import React from 'react';
import { tracing } from '@opencensus/web-core';

class App extends React.Component {

Expand All @@ -29,21 +30,34 @@ class App extends React.Component {
handleClick() {
// Use promises to test behavior on MicroTasks.
const promise = new Promise(resolve => {
// Start a child span for the setTimeout as this is the operation we want
// to measure.
// This span will be child of the current root span related to the
// current user interaction. Additionally, these spans should be created
// in the code the click handler will run.
const setTimeoutCustomSpan = tracing.tracer.startChildSpan({ name: 'setTimeout custom span' });
setTimeout(function () {
resolve();
// End the span as the setTimeout has finished running the callback.
setTimeoutCustomSpan.end();
}, 1000);
});

promise.then(() => {
console.log("Resolving promise");
this.callSleepApi();
});
}

callSleepApi() {
const xhr = new XMLHttpRequest();
// Create a child span for the XHR. It is possible to create your own spans
// even if the involved task or operation already generates an automatic
// span. In this case, automatic spans are generated for XHRs.
const callSleepApiCustomSpan = tracing.tracer.startChildSpan({ name: 'Call Sleep API' });
Copy link
Contributor

Choose a reason for hiding this comment

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

What would you think about removing this custom span since there will already be one for the XHR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would like to keep it. My thought is to show in the example that is possible to create custom spans even if those tasks already generate automatic spans. I will add some comments to clarify more this example.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, I think it's fine to keep. Is there another call that does not have a custom span on it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, the call to prime numbers API does not have a custom span, as it also is an XHR, I decided to not create a custom span for that.

xhr.onreadystatechange = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
// End the XHR span once it is DONE.
callSleepApiCustomSpan.end();
this.callPrimeNumbersApi();
}
};
Expand All @@ -66,10 +80,11 @@ class App extends React.Component {
}

callCalculatePi() {
// Start span for synchronous code.
const calculatePiCustomSpan = tracing.tracer.startChildSpan({ name: 'Calculate PI' });
const time = Date.now();
console.log("Calculating PI");
const pi = this.calculatePi();
console.log("Finished calculating PI");
calculatePiCustomSpan.end();
return { time: (Date.now() - time), value: pi };
}

Expand Down
2 changes: 1 addition & 1 deletion examples/user_interaction/client/src/SecondPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* gRPC://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
Expand Down
2 changes: 1 addition & 1 deletion examples/user_interaction/client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* gRPC://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
Expand Down
29 changes: 26 additions & 3 deletions packages/opencensus-web-instrumentation-zone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,31 @@ The library is in alpha stage and the API is subject to change.

## Usage

Currently the primary intended usage of OpenCensus Web is to collect
spans from the resource timing waterfall of an initial page load. See the
[OpenCensus Web readme][oc-web-readme-url] for details.
#### Custom spans
In addition to automatic user interaction tracing, it is possible to create
your own spans for the tasks or code involved in a user interaction.
Here is an example for JavaScript

```javascript
import { tracing } from '@opencensus/web-core';

function handleClick() {
// Start child span which will be child of the current root span on the current interaction.
// To make sure the span is attached to the root span, add this in code that the button is running.
const childSpan = tracing.tracer.startChildSpan({
name: 'name of your child span'
});
// Do some operation...
// Finish the child span at the end of it's operation
childSpan.end();
}

// Create a fake button to point out the custom span is created in the click handler.
const button = document.createElement('button');
button.onclick = handleClick;
```
Check the [user interaction client example][client-example-url] which instruments the package and
create some custom spans.

## Useful links
- For more information on OpenCensus, visit: <https://opencensus.io/>
Expand All @@ -31,3 +53,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[nav-timing-url]: https://www.w3.org/TR/navigation-timing-2/
[resource-timing-url]: https://www.w3.org/TR/resource-timing-2/
[long-tasks-url]: https://w3c.github.io/longtasks/
[client-example-url]: https://github.com/census-instrumentation/opencensus-web/tree/master/examples/user_interaction/client
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,40 @@ describe('InteractionTracker', () => {
});
});

describe('Custom Spans', () => {
it('Should handle the custom spans and add them to the current root span as child spans', done => {
const onclick = () => {
// Start a custom span for the setTimeout.
const setTimeoutCustomSpan = tracing.tracer.startChildSpan({
name: 'setTimeout custom span',
});
setTimeout(() => {
setTimeoutCustomSpan.end();
}, SET_TIMEOUT_TIME);
};
fakeInteraction(onclick);

onEndSpanSpy.and.callFake((rootSpan: Span) => {
expect(rootSpan.name).toBe('test interaction');
expect(rootSpan.attributes['EventType']).toBe('click');
expect(rootSpan.attributes['TargetElement']).toBe(BUTTON_TAG_NAME);
expect(rootSpan.ended).toBeTruthy();
expect(rootSpan.spans.length).toBe(1);
const childSpan = rootSpan.spans[0];
expect(childSpan.name).toBe('setTimeout custom span');
expect(childSpan.duration).toBeGreaterThanOrEqual(SET_TIMEOUT_TIME);
expect(childSpan.duration).toBeLessThanOrEqual(
SET_TIMEOUT_TIME + TIME_BUFFER
);
expect(rootSpan.duration).toBeGreaterThanOrEqual(SET_TIMEOUT_TIME);
expect(rootSpan.duration).toBeLessThanOrEqual(
SET_TIMEOUT_TIME + TIME_BUFFER
);
done();
});
});
});

describe('HTTP requests', () => {
// Value to be full when the XMLHttpRequest.send method is faked,
// That way the perfornamce resource entries have a accurate timing.
Expand Down