Skip to content

Commit

Permalink
Go: Add Registering Views (#3275)
Browse files Browse the repository at this point in the history
Co-authored-by: Fabrizio Ferri-Benedetti <[email protected]>
Co-authored-by: David Ashpole <[email protected]>
  • Loading branch information
3 people authored Sep 18, 2023
1 parent b57be88 commit 5cb4b0d
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 15 deletions.
8 changes: 4 additions & 4 deletions content/en/docs/concepts/signals/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ Some examples of use cases for metrics include:

## Views

A View provides SDK users with the flexibility to customize the metrics that are
output by the SDK. They can customize which metric instruments are to be
processed or ignored. They can customize aggregation and what attributes are to
be reported on metrics.
A view provides SDK users with the flexibility to customize the metrics output
by the SDK. You can customize which metric instruments are to be processed or
ignored. You can also customize aggregation and what attributes you want to
report on metrics.

## Language Support

Expand Down
112 changes: 103 additions & 9 deletions content/en/docs/instrumentation/go/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,7 @@ example).

Counters can be used to measure a non-negative, increasing value.

For example, here's how you might report the number of calls for an HTTP
handler:
For example, here's how you report the number of calls for an HTTP handler:

```go
import (
Expand Down Expand Up @@ -497,7 +496,7 @@ func init() {
UpDown counters can increment and decrement, allowing you to observe a
cumulative value that goes up or down.

For example, here's how you might report the number of items of some collection:
For example, here's how you report the number of items of some collection:

```go
import (
Expand Down Expand Up @@ -537,8 +536,8 @@ func removeItem() {

Histograms are used to measure a distribution of values over time.

For example, here's how you might report a distribution of response times for an
HTTP handler:
For example, here's how you report a distribution of response times for an HTTP
handler:

```go
import (
Expand Down Expand Up @@ -573,7 +572,7 @@ func init() {
Observable counters can be used to measure an additive, non-negative,
monotonically increasing value.

For example, here's how you might report time since the application started:
For example, here's how you report time since the application started:

```go
import (
Expand Down Expand Up @@ -604,7 +603,7 @@ func init() {
Observable UpDown counters can increment and decrement, allowing you to measure
an additive, non-negative, non-monotonically increasing cumulative value.

For example, here's how you might report some database metrics:
For example, here's how you report some database metrics:

```go
import (
Expand Down Expand Up @@ -656,8 +655,8 @@ func registerDBMetrics(db *sql.DB, meter metric.Meter, poolName string) (metric.

Observable Gauges should be used to measure non-additive values.

For example, here's how you might report memory usage of the heap objects used
in application:
For example, here's how you report memory usage of the heap objects used in
application:

```go
import (
Expand Down Expand Up @@ -720,6 +719,101 @@ func init() {
}
```

### Registering Views

A view provides SDK users with the flexibility to customize the metrics output
by the SDK. You can customize which metric instruments are to be processed or
ignored. You can also customize aggregation and what attributes you want to
report on metrics.

Every instrument has a default view, which retains the original name,
description, and attributes, and has a default aggregation that is based on the
type of instrument. When a registered view matches an instrument, the default
view is replaced by the registered view. Additional registered views that match
the instrument are additive, and result in multiple exported metrics for the
instrument.

You can use the
[`NewView`](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric#NewView)
function to create a view and register it using the
[`WithView`](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric#WithView)
option.

For example, here's how you create a view that renames the `latency` instrument
from the `v0.34.0` version of the `http` instrumentation library to
`request.latency`:

```go
view := metric.NewView(metric.Instrument{
Name: "latency",
Scope: instrumentation.Scope{
Name: "http",
Version: "0.34.0",
},
}, metric.Stream{Name: "request.latency"})

meterProvider := metric.NewMeterProvider(
metric.WithView(view),
)
```

For example, here's how you create a view that makes the `latency` instrument
from the `http` instrumentation library to be reported as an exponential
histogram:

```go
view := metric.NewView(
metric.Instrument{
Name: "latency",
Scope: instrumentation.Scope{Name: "http"},
},
metric.Stream{
Aggregation: metric.AggregationBase2ExponentialHistogram{
MaxSize: 160,
MaxScale: 20,
},
},
)

meterProvider := metric.NewMeterProvider(
metric.WithView(view),
)
```

The `NewView` function provides a convenient way of creating views. If `NewView`
can't provide the functionalities you need, you can create a custom
[`View`](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric#View) directly.

For example, here's how you create a view that uses regular expression matching
to ensure all data stream names have a suffix of the units it uses:

```go
re := regexp.MustCompile(`[._](ms|byte)$`)
var view metric.View = func(i metric.Instrument) (metric.Stream, bool) {
// In a custom View function, you need to explicitly copy
// the name, description, and unit.
s := metric.Stream{Name: i.Name, Description: i.Description, Unit: i.Unit}
// Any instrument that does not have a unit suffix defined, but has a
// dimensional unit defined, update the name with a unit suffix.
if re.MatchString(i.Name) {
return s, false
}
switch i.Unit {
case "ms":
s.Name += ".ms"
case "By":
s.Name += ".byte"
default:
return s, false
}
return s, true
}

meterProvider := metric.NewMeterProvider(
metric.WithView(view),
)
```

## Logs

The logs API is currently unstable, documentation TBA.
Expand Down
4 changes: 2 additions & 2 deletions content/en/docs/instrumentation/js/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -1452,8 +1452,8 @@ counter.add(-1);

Histograms are used to measure a distribution of values over time.

For example, here's how you might report a distribution of response times for an
API route with Express:
For example, here's how you report a distribution of response times for an API
route with Express:

{{< tabpane text=true langEqualsHeader=true >}} {{% tab TypeScript %}}

Expand Down
16 changes: 16 additions & 0 deletions static/refcache.json
Original file line number Diff line number Diff line change
Expand Up @@ -4391,6 +4391,22 @@
"StatusCode": 200,
"LastSeen": "2023-09-11T14:33:25.420952095Z"
},
"https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric#NewView": {
"StatusCode": 200,
"LastSeen": "2023-09-15T09:41:38.164411819Z"
},
"https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric#View": {
"StatusCode": 200,
"LastSeen": "2023-09-15T09:41:38.432556144Z"
},
"https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric#With": {
"StatusCode": 200,
"LastSeen": "2023-09-15T09:41:38.295762202Z"
},
"https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric#WithView": {
"StatusCode": 200,
"LastSeen": "2023-09-15T16:34:14.034832295Z"
},
"https://pkg.go.dev/go.opentelemetry.io/otel/sdk/resource": {
"StatusCode": 200,
"LastSeen": "2023-09-11T14:33:25.721659015Z"
Expand Down

0 comments on commit 5cb4b0d

Please sign in to comment.