Skip to content

Commit

Permalink
Update README
Browse files Browse the repository at this point in the history
- and rename ci > build
  • Loading branch information
jjti committed Dec 27, 2023
1 parent 30fa209 commit f97736d
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml → .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI
name: build

on:
push:
Expand Down
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,49 @@
# go-spanlint

![Latest release](https://img.shields.io/github/v/release/jjti/go-spanlint)
[![CI](https://github.com/jjti/go-spanlint/actions/workflows/ci.yaml/badge.svg)](https://github.com/jjti/go-spanlint/actions/workflows/ci.yaml)
[![build](https://github.com/jjti/go-spanlint/actions/workflows/build.yaml/badge.svg)](https://github.com/jjti/go-spanlint/actions/workflows/build.yaml)
[![Go Report Card](https://goreportcard.com/badge/github.com/jjti/go-spanlint)](https://goreportcard.com/report/github.com/jjti/go-spanlint)
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)

Checks usage of [OpenTelemetry spans](https://pkg.go.dev/go.opentelemetry.io/otel/trace).

## Problem Statement

Tracing is one of the pillars of observability. But it's easy to shoot yourself in the foot when creating and managing OTEL spans. For two reasons:

### Forgetting to call `span.End()`

Not calling `.End()` can cause memory leaks.

> Any Span that is created MUST also be ended. This is the responsibility of the user. Implementations of this API may leak memory or other resources if Spans are not ended.
[source: trace.go](https://github.com/open-telemetry/opentelemetry-go/blob/98b32a6c3a87fbee5d34c063b9096f416b250897/trace/trace.go#L523)

```go
func task(ctx context.Context) error {
otel.Tracer().Start(ctx, "foo") // span is unassigned, probable memory leak
_, span := otel.Tracer().Start(ctx, "foo") // span.End is not called on all paths, possible memory leak
return nil // this return statement may be reached without calling span.End
}
```

### Forgetting to call `span.SetStatus(codes.Error, "msg")`

Setting spans' status to `codes.Error` matters for a couple reasons.

First, observability platforms and APMs differentiate "success" vs "failure" using [span's status codes](https://docs.datadoghq.com/tracing/metrics/).

Second, telemetry collector agents, like the [Open Telemetry Collector](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/tailsamplingprocessor/README.md#:~:text=Sampling%20Processor.-,status_code,-%3A%20Sample%20based%20upon), are configurable to sample `Error` spans at a higher rate than `OK` spans. Similarly, observability platforms like DataDog support trace retention filters based on spans' status. In other words, `Error` spans often receive special treatment with the assumption they are more useful for debugging.

```go
func _() error {
_, span := otel.Tracer("foo").Start(context.Background(), "bar") // span.SetStatus is not called on all paths
defer span.End()

if true {
return errors.New("foo") // this return statement may be reached without calling span.SetStatus
}

return nil
}
```

0 comments on commit f97736d

Please sign in to comment.