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

Simplify and make js manual doc more correct #1435

Closed
Closed
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
159 changes: 78 additions & 81 deletions content/en/docs/instrumentation/js/instrumentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ title: Instrumentation
weight: 3
---

This guide will cover creating and annotating spans, creating and annotating metrics, how to pass context, and a guide to automatic instrumentation for JavaScript. This simple example works in the browser as well as with Node.js
This guide will cover creating and annotating spans, creating and annotating
metrics, how to pass context, and a guide to automatic instrumentation for
JavaScript. This simple example works in the browser as well as with Node.js
cartermp marked this conversation as resolved.
Show resolved Hide resolved

## Example Application

Expand All @@ -25,29 +27,32 @@ function doWork() {

## Initializing a Tracer

As you have learned in the previous [Getting Started](../getting-started) guide you
need a TracerProvider and an Exporter. Install the dependencies and add them to
the head of your application code to get started:
As you have learned in the previous [Getting Started](../getting-started) guide
cartermp marked this conversation as resolved.
Show resolved Hide resolved
you need a TracerProvider and an Exporter. Install the dependencies and add them
to the head of your application code to get started:

```shell
npm install @opentelemetry/api
npm install @opentelemetry/sdk-trace-base
```

Next, initialize a tracer, preferably in a separate file (e.g., `instrumentation-setup.js`):
Next, initialize a tracer, preferably in a separate file (e.g.,
`instrumentation-setup.js`):

```javascript
const {
BasicTracerProvider,
ConsoleSpanExporter,
SimpleSpanProcessor,
BatchSpanProcessor,
cartermp marked this conversation as resolved.
Show resolved Hide resolved
} = require('@opentelemetry/sdk-trace-base');
const opentelemetry = require('@opentelemetry/api');

const provider = new BasicTracerProvider();

// Configure span processor to send spans to the exporter
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
const exporter = new ConsoleSpanExporter()
const processor = new BatchSpanProcessor(exporter)
provider.addSpanProcessor(processor);
provider.register();

// This is what we'll access in all instrumentation code
Expand All @@ -56,9 +61,11 @@ export const tracer = opentelemetry.trace.getTracer(
);
```

This registers a tracer provider with the OpenTelemetry API as the global tracer provider, and exports a tracer instance that you can use to create spans.
This registers a tracer provider with the OpenTelemetry API as the global tracer
provider, and exports a tracer instance that you can use to create spans.

If you do not register a global tracer provider, any instrumentation calls will be a no-op, so this is important to do!
If you do not register a global tracer provider, any instrumentation calls will
be a no-op, so this is important to do!
cartermp marked this conversation as resolved.
Show resolved Hide resolved

## Create spans

Expand Down Expand Up @@ -93,25 +100,30 @@ Run your application and you will see traces being exported to the console:

## Create nested spans

Nested spans let you track work that's nested in nature. For example, the `doWork` function below represents a nested operation. The following sample creates a nested span that tracks the `doWork` function:
Nested spans let you track work that's nested in nature. For example, the
`doWork` function below represents a nested operation. The following sample
creates a nested span that tracks the `doWork` function:

```javascript
// Create a span. A span must be closed.
const parentSpan = tracer.startSpan('main');
for (let i = 0; i < 10; i += 1) {
doWork(parentSpan);
}
const mainWork = () => {
const parentSpan = tracer.startSpan('main');

for (let i = 0; i < 3; i += 1) {
doWork(parentSpan, i);
}

/* ... */
// Be sure to end the parent span!
parentSpan.end();
}

function doWork(parent) {
// Start another span. In this example, the main function already started a
// span, so that'll be the parent span, and this will be a child span.
function doWork(parent, i) {
// To set a child span, we need to mark the parent span as the active span
cartermp marked this conversation as resolved.
Show resolved Hide resolved
// in the context, then use the resulting context to create a child span.
const ctx = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
parent
);
const span = tracer.startSpan('doWork', undefined, ctx);
const span = tracer.startSpan(`doWork:${i}`, undefined, ctx);

// simulate some random work.
for (let i = 0; i <= Math.floor(Math.random() * 40000000); i += 1) {
Expand All @@ -122,16 +134,15 @@ function doWork(parent) {
// it will continue to track work beyond 'doWork'!
span.end();
}

// Be sure to end the parent span.
parentSpan.end();
```

If you run the application again, you'll see the parent span and then a span for each call to `doWork`, each listing `parentSpan`'s ID as its `parentId`.
This code will create 3 child spans that have `parentSpan`'s span ID as their
parent IDs.

## Get the current span

Sometimes it's helpful to do something with the current/active span at a particular point in program execution.
Sometimes it's helpful to do something with the current/active span at a
particular point in program execution.

```js
const span = opentelemetry.trace.getSpan(opentelemetry.context.active());
Expand All @@ -141,37 +152,30 @@ const span = opentelemetry.trace.getSpan(opentelemetry.context.active());

## Attributes

Attributes can be used to describe your spans. Attributes can be added to a span at any time before the span is finished:
Attributes can be used to describe your spans. Attributes can be added to a span
at any time before the span is finished:

```javascript
function doWork(parent) {
const ctx = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
parent
);

// Add an attribute to a span at the time of creation
const span = tracer.startSpan(
'doWork',
{ attributes: { attribute1: 'value1' } },
ctx
);

for (let i = 0; i <= Math.floor(Math.random() * 40000000); i += 1) {
// empty
}
const span = tracer.startSpan(
'app.new-span',
{ attributes: { attribute1: 'value1' } },
ctx
);

// Add an attribute to the same span later on
span.setAttribute('attribute2', 'value2');
// Add an attribute to the same span later on
span.setAttribute('attribute2', 'value2');

// Be sure to end the span!
span.end();
}
// Make sure to end the span if you're done with it!
span.end();
```

### Semantic Attributes

There are semantic conventions for spans representing operations in well-known protocols like HTTP or database calls. Semantic conventions for these spans are defined in the specification at [Trace Semantic Conventions]({{< relref "/docs/reference/specification/trace/semantic_conventions" >}}). In the simple example of this guide the source code attributes can be used.
There are semantic conventions for spans representing operations in well-known
protocols like HTTP or database calls. Semantic conventions for these spans are
defined in the specification at [Trace Semantic Conventions]({{< relref
"/docs/reference/specification/trace/semantic_conventions" >}}). In the simple
example of this guide the source code attributes can be used.

First add the semantic conventions as a dependency to your application:

Expand All @@ -188,27 +192,26 @@ const { SemanticAttributes } = require('@opentelemetry/semantic-conventions');
Finally, you can update your file to include semantic attributes:

```javascript
function doWork(parent) {
const ctx = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
parent
);
const doWork = () => {
const span = tracer.startSpan(
'doWork',
'app.new-span',
{ attributes: { [SemanticAttributes.CODE_FUNCTION]: 'doWork' } },
ctx
);
for (let i = 0; i <= Math.floor(Math.random() * 40000000); i += 1) {
// empty
}

// Add an attribute to the same span later on
span.setAttribute(SemanticAttributes.CODE_FILEPATH, __filename);

// Make sure to end the span if you're done with it!
span.end();
}
```

## Span events

An event is a human-readable message attached to a span that represents "something happening" during its lifetime. You can think of it like a primitive log.
An event is a human-readable message attached to a span that represents
"something happening" during its lifetime. You can think of it like a primitive
cartermp marked this conversation as resolved.
Show resolved Hide resolved
log.

```js
span.addEvent('Doing something');
Expand Down Expand Up @@ -252,37 +255,31 @@ function someFunction(spanToLinkFrom) {

## Span Status

A status can be set on a span, typically to indicate that it did not complete
successuflly - `SpanStatusCode.ERROR`. In rare situations, you may wish to
override this with `SpanStatusCode.OK`. But don't set the status to `OK`
each time a span successfully completes.

The status can be set at any time before the span is finished:
A status can be set on a span, typically used to specify that there was an error
in the operation a span is tracking - .`Error`.

```javascript
function doWork(parent) {
const ctx = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
parent
);
const span = tracer.startSpan('doWork', undefined, ctx);

for (let i = 0; i <= Math.floor(Math.random() * 40000000); i += 1) {
if (i > 10000) {
span.setStatus({
code: opentelemetry.SpanStatusCode.ERROR,
message: 'Error'
});
}
const span = tracer.startSpan('doWork', undefined, ctx);

for (let i = 0; i <= Math.floor(Math.random() * 40000000); i += 1) {
if (i > 10000) {
span.setStatus({
code: opentelemetry.SpanStatusCode.ERROR,
message: 'Error'
});
}

span.end();
}

span.end();
```

By default, the status for all spans is `Unset`. In rare cases, you may also
wish to set the status to `Ok`. This should generally not be necessary, though.
cartermp marked this conversation as resolved.
Show resolved Hide resolved

## Recording exceptions

It can be a good idea to record exceptions when they happen. It's recommended to do this in conjunction with setting [span status](#span-status).
It can be a good idea to record exceptions when they happen. It's recommended to
do this in conjunction with setting [span status](#span-status).

```js
try {
Expand Down