Skip to content

Commit

Permalink
docs(README): add usage examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Strazz1337 committed Oct 3, 2024
1 parent 03b5888 commit f4d49c7
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 37 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ The aim of this package is to provide some additional tools on top of the offici

We, at Zonneplan, have different (mono) repositories that utilize the power of OpenTelemetry. We built out a small internal package to let us easily integrate OpenTelemetry in our NestJS applications, with as few lines of code as necessary. Furthermore, we wanted to provide some tools to easily use metrics and spans in our applications. We decided that our tools may be useful for other people and thus decided to open-source it.

## Getting started

See the README in the [open-telemetry-node](./packages/open-telemetry-node/README.md) package for a quick start guide.

## Packages

This repository contains the following packages:
Expand Down
52 changes: 52 additions & 0 deletions packages/open-telemetry-nest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,55 @@
```
npm install @zonneplan/open-telemetry-nest
```

## Usage

### Using metrics

```typescript
import { createCounterProvider, Counter } from '@zonneplan/open-telemetry-nest';

const MY_METRIC = 'my_metric';

// my-module.ts
@Module({
providers: [
/**
* Registers a counter provider, which can be injected in services.
*/
createCounterProvider({
name: MY_METRIC,
description: 'My metric description',
unit: 'occurrences',
valueType: ValueType.INT,
})
]
})
export class MyModule {}

// my-service.ts
@Injectable()
export class MyService {
constructor(
/**
* Inject the metric in the service.
*/
@InjectMetric(MY_METRIC) private readonly myMetric: Counter
) {}

/**
* Using the default metric methods.
*/
public myMethod() {
this.myMetric.add(1);
}

/**
* Using the metric increment decorator.
*/
@metricIncrement(MY_METRIC)
public myMetricIncrementDecorator() {

}
}
```
98 changes: 61 additions & 37 deletions packages/open-telemetry-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ npm install @zonneplan/open-telemetry-node

## Usage

**Initialize OpenTelemetry before your application bootstraps**
### Initialize OpenTelemetry before your application bootstraps

The usage of `import ... = require('')` is necessary so that the types are loaded in before the application is bootstrapped. Otherwise, the instrumentations are not loaded in time. This code would be placed on top of the `main.ts` in a NestJS application. For example, see [main.ts](../../examples/nest-app/src/main.ts)

Expand Down Expand Up @@ -61,11 +61,68 @@ new otel.OpenTelemetryBuilder('nest-example')
.start();
```

**Use metrics**

### Using spans (tracing)

```typescript
// We provide our own Gauge instance here and not the ObservableGauge from OpenTelemetry
// This is the mimic the behaviour of a Prometheus Gauge (from prom-client)
import { setAttributeOnActiveSpan } from './set-attributes-on-active-span';
import { setSpanError } from './set-span-status';

@Injectable()
export class MyService {
/**
* Instead of manually starting a span, you can use the {@link span} decorator to automatically start a span for the given method.
* Alternatively, use the `startSpan` method using the disposable pattern / manually ending it.
* The span name can be overwritten, but defaults to AppService::getData.
*
* @note decorators require the following config options in the `tsconfig.json`:
* "emitDecoratorMetadata": true,
* "experimentalDecorators": true
*/
@span()
/**
* Span attributes can be manually set in the method, by using the `setAttributeOnActiveSpan` method.
* However, if you only want to set some input parameters as span attributes, you can use the {@link spanAttribute} decorator.
*
* @note primitive values (string, numbers and booleans) don't need a function for parsing. Other's do, because they are not valid span attribute values.
* the name is automatically inferred, but technically does not match the Open telemetry spec, so it's recommended to always provide a name.
*/
public methodWithSpanDecorator(@spanAttribute((val: Date) => val.toISOString()) date: Date, @spanAttribute() name: string) {
setAttributeOnActiveSpan('name', name);
setSpanError('This is an error');
}

public methodWithSpan() {
const span = startSpan('methodWithSpan');

span.setAttribute('name', 'John Doe');
span.setStatus({
code: SpanStatusCode.ERROR,
message: 'This is an error'
});

span.end();
}

public methodWithDisposableSpan() {
let span: Span;

if (true) {
using span = startSpan('methodWithDisposableSpan');
span.end();
}

span.isRecording(); // false
}
}
```


### Using metrics

```typescript
// We provide our own Gauge instance here to mimic the behaviour of a Prometheus Gauge (from prom-client)
// this is mainly because we use gauages for tracking time-related tasks, so we provide a simple utility to set the gauge to the current time.
const gauge = getOrCreateMetric({
name: 'process_boot_time',
unit: 's',
Expand Down Expand Up @@ -102,36 +159,3 @@ class MyClass {
}
}
```

**Use tracing**

```typescript
@Injectable()
export class MyService {
/**
* Instead of manually starting a span, you can use the {@link span} decorator to automatically start a span for the given method.
* Alternatively, use the `startSpan` method using the disposable pattern / manually ending it.
* The span name can be overwritten, but defaults to AppService::getData.
*
* @note decorators require the following config options in the `tsconfig.json`:
* "emitDecoratorMetadata": true,
* "experimentalDecorators": true
*/
@span()
/**
* Span attributes can be manually set in the method, by using the `setAttributeOnActiveSpan` method.
* However, if you only want to set some input parameters as span attributes, you can use the {@link spanAttribute} decorator.
*
* @note primitive values (string, numbers and booleans) don't need a function for parsing. Other's do, because they are not valid span attribute values.
* the name is automatically inferred, but technically does not match the Open telemetry spec, so it's recommended to always provide a name.
*/
getData(@spanAttribute((val: Date) => val.toISOString()) date: Date, @spanAttribute() name: string): {
message: string
} {
this.getCounter.add(1);
this.logger.log('getData called', { name, date: date.toISOString() });

return { message: `Hello ${name}, today is ${date.toDateString()}` };
}
}
```

0 comments on commit f4d49c7

Please sign in to comment.