ballerina/observe : 0.9.0

Module Overview

This module provides an API for observing Ballerina services. Ballerina supports Observability out of the box. This module provides an API to make observability more flexible for the Ballerina users.

To observe the Ballerina code, the '--b7a.observability.enabled=true' property should be given when starting the service (i.e., `ballerina run hello_world.bal --b7a.observability.enabled=true').

Tracing

Tracing provides information regarding the roundtrip of a service invocation based on the concept of spans, which are structured in a hierarchy based on the cause and effect concept. The tracing API allows users to tap into that tracing information, introduce new spans, and add additional information to existing spans using user-defined tags.

Samples

Start a root span & attach a child span

The following code snippet shows an example of starting a root span with no parent and starting another span as a child of the first span. Note: Make sure that all started spans are closed properly to ensure that all spans are reported properly.

1int spanId = observe:startRootSpan("Parent Span");
2
3// Do Something.
4
5int spanId2 = checkpanic observe:startSpan("Child Span", parentSpanId = spanId);
6
7// Do Something.
8
9var ret1 = observe:finishSpan(spanId2);
10
11// Do Something.
12
13var ret2 = observe:finishSpan(spanId);

Start a span attached to a system trace

When no parentSpanId is given or a parentSpanId of -1 is given, a span is started as a child span to the current active span in the ootb system trace.

1int spanId = checkpanic observe:startSpan("Child Span");
2
3// Do Something.
4
5var ret = observe:finishSpan(spanId);

Attach a tag to a span

It is possible to add tags to the span by using the observe:addTagToSpan() function by providing the span id and relevant tag key and tag value.

1_ = observe:addTagToSpan(spanId = spanId, "Tag Key", "Tag Value");

Attach a tag to a span in the system trace

When no spanId is provided or -1 is given, the defined tags are added to the current active span in the ootb system trace.

1var ret = observe:addTagToSpan("Tag Key", "Tag Value");

Metrics

There are mainly two kind of metrics instances supported; Counter and Gauge. A counter is a cumulative metric that represents a single monotonically increasing counter whose value can only increase or be reset to zero on restart. For example, you can use a counter to represent the number of requests served, tasks completed, or errors. The Gauge metric instance represents a single numerical value that can arbitrarily go up and down, and also based on the statistics configurations provided to the Gauge, it can also report the statistics such as max, min, mean, percentiles, etc.

Counter Samples

Create

The following code snippets provides the information on how Counter instances can be created. Instantiating the counter will simply create an instance based on the params passed.

1// Create counter with simply by name.
2observe:Counter simpleCounter = new("SimpleCounter");
3
4// Create counter with description.
5observe:Counter counterWithDesc = new("CounterWithDesc",
6 desc = "This is a sample counter description");
7
8// Create counter with tags.
9map<string> counterTags = { "method": "GET" };
10observe:Counter counterWithTags = new("CounterWithTags",
11 desc = "Some description", tags = counterTags);

Register

The counter can be registered with the global metrics registry. Therefore, it can be looked up later without having the reference of the counter that was created. Also, only the registered counters will be reported to the Metrics reporter such as Prometheus. In case, if there is already another non counter metric registered, then there will be an error returned. But if it's another counter instance, then the registered counter instance will be returned.

1map<string> counterTags = { "method": "GET" };
2observe:Counter counterWithTags = new("CounterWithTags",
3 desc = "Some description", tags = counterTags);
4var anyError = counterWithTags.register();
5if anyError is error {
6 log:printError("Cannot register the counter", err = anyError);
7}

Unregister

The counter can be unregistered with the global metrics registry if it is already registered. If a metrics is unregistered, then further it'll not be included in metrics reporting.

1map<string> counterTags = { "method": "GET" };
2observe:Counter counterWithTags = new("CounterWithTags",
3 desc = "Some description", tags = counterTags);
4var anyError = counterWithTags.register();
5if anyError is error {
6 log:printError("Cannot register the counter", err = anyError);
7}
8counterWithTags.unregister();
9

Increment

The counter can be incremented without passing any params (defaulted to 1), or by a specific amount.

1map<string> counterTags = { "method": "GET" };
2observe:Counter counterWithTags = new("CounterWithTags",
3 desc = "Some description", tags = counterTags);
4// Increment by 1.
5counterWithTags.increment();
6// Increment by amount 10.
7counterWithTags.increment(amount = 10);

Reset

The counter can be resetted to default amount = 0.

1map<string> counterTags = { "method": "GET" };
2observe:Counter counterWithTags = new("CounterWithTags",
3 desc = "Some description", tags = counterTags);
4counterWithTags.reset();

Get Value

The current value can be retrieved by this operation.

1map<string> counterTags = { "method": "GET" };
2observe:Counter counterWithTags = new("CounterWithTags",
3 desc = "Some description", tags = counterTags);
4int currentValue = counterWithTags.getValue();

Gauge Samples

Create

The following code snippets provides the information on how Gauge instances can be created. Instantiating the gauge will simply create an instance based on the params passed.

1// Create gauge with simply by name.
2// Uses the default statistics configuration.
3observe:Gauge simpleGauge = new("SimpleGauge");
4
5// Create gauge with description.
6// Uses the default statistics configuration.
7observe:Gauge gaugeWithDesc = new("GaugeWithDesc",
8 desc = "This is a sample gauge description");
9
10// Create gauge with tags.
11// Uses the default statistics configuration.
12map<string> gaugeTags = { "method": "GET" };
13observe:Counter gaugeWithTags = new("GaugeWithTags",
14 desc = "Some description", tags = gaugeTags);
15
16// Create gauge with disabled statistics.
17observe:StatisticConfig[] statsConfigs = [];
18observe:Gauge gaugeWithNoStats = new("GaugeWithTags",
19 desc = "Some description", tags = gaugeTags, statisticConfig = statsConfigs);
20
21// Create gauge with statistics config.
22observe:StatisticConfig config = { timeWindow: 30000,
23 percentiles: [0.33, 0.5, 0.9, 0.99], buckets: 3 };
24statsConfigs[0]=config;
25
26observe:Gauge gaugeWithStats = new("GaugeWithTags",
27 desc = "Some description", tags = gaugeTags, statisticConfig = statsConfigs);

Register

The gauge can be registered with the global metrics registry, therefore it can be looked up later without having the reference of the gauge that was created. Also, only the registered counters will be reported to the Metrics reporter such as Prometheus. In case, if there is already another non gauge metric registered, then there will be an error returned. But if it's another gauge instance, then the registered gauge instance will be returned.

1map<string> gaugeTags = { "method": "GET" };
2observe:Gauge gaugeWithTags = new("GaugeWithTags",
3 desc = "Some description", tags = gaugeTags);
4var anyError = gaugeWithTags.register();
5if anyError is error {
6 log:printError("Cannot register the gauge", err = anyError);
7}

Unregister

The gauge can be unregistered with the global metrics registry if it is already registered. If a metrics is unregistered, then further it'll not be included in metrics reporting.

1map<string> gaugeTags = { "method": "GET" };
2observe:Gauge gaugeWithTags = new("GaugeWithTags",
3 desc = "Some description", tags = gaugeTags);
4var anyError = gaugeWithTags.register();
5if anyError is error {
6 log:printError("Cannot register the gauge", err = anyError);
7}
8gaugeWithTags.unregister();

Increment

The gauge can be incremented without passing any params (defaulted to 1.0), or by a specific amount.

1map<string> gaugeTags = { "method": "GET" };
2observe:Gauge gaugeWithTags = new("GaugeWithTags",
3 desc = "Some description", tags = gaugeTags);
4// Increment by 1.
5gaugeWithTags.increment();
6// Increment by amount 10.
7gaugeWithTags.increment(amount = 10.0);

Decrement

The gauge can be decremented without passing any params (defaulted to 1.0), or by a specific amount.

1map<string> gaugeTags = { "method": "GET" };
2observe:Gauge gaugeWithTags = new("GaugeWithTags",
3 desc = "Some description", tags = gaugeTags);
4// Increment by 1.
5gaugeWithTags.decrement();
6// Increment by amount 10.
7gaugeWithTags.decrement(amount = 10.0);

Set Value

This method sets the gauge's value with specific amount.

1map<string> gaugeTags = { "method": "GET" };
2observe:Gauge gaugeWithTags = new("GaugeWithTags",
3 desc = "Some description", tags = gaugeTags);
4gaugeWithTags.setValue(100.0);

Get Value

The current value can be retrieved by this operation.

1map<string> gaugeTags = { "method": "GET" };
2observe:Gauge gaugeWithTags = new("GaugeWithTags",
3 desc = "Some description", tags = gaugeTags);
4float currentValue = gaugeWithTags.getValue();

Get Snapshot

This method retrieves current snapshot of the statistics calculation based on the configurations passed to the gauge. If the statistics are disabled, then it'll be returning nil ().

1map<string> gaugeTags = { "method": "GET" };
2observe:Gauge gaugeWithTags = new("GaugeWithTags",
3 desc = "Some description", tags = gaugeTags);
4gaugeWithTags.setValue(1.0);
5gaugeWithTags.setValue(2.0);
6gaugeWithTags.setValue(3.0);
7
8observe:Snapshot[]? summarySnapshot = gaugeWithTags.getSnapshot();
9if summarySnapshot is observe:Snapshot[] {
10 io:println(summarySnapshot);
11} else {
12 io:println("No statistics available!");
13}

Global Metrics Samples

Get All Metrics

This method returns all the metrics that are registered in the global metrics registry. This method is mainly useful for metric reporters, where they can fetch all metrics, format those, and report.

1observe:Metric[] metrics = observe:getAllMetrics();
2foreach var metric in metrics {
3 // Do something.
4}

Lookup Metric

This method will lookup for the metric from the global metric registry and return it.

1map<string> tags = { "method": "GET" };
2observe:Counter|observe:Gauge|() metric = observe:lookupMetric("MetricName",
3 tags = tags);
4if metric is observe:Counter {
5 metric.increment(amount = 10);
6} else if metric is observe:Gauge {
7 metric.increment(amount = 10.0);
8} else {
9 io:println("No Metric Found!");
10}

Modules

[2]

observe

This module provides an API for observing Ballerina services.

observe.mockextension

This module provides an API for accessing observability mock functionality.

Functions

[14]

addTagToMetrics

Add a key value pair as a tag to system metrics.

addTagToSpan

Add a key value pair as a tag to the span.

finishSpan

Finish the current span.

getAllMetrics

Retrieve all registered metrics including default metrics from the ballerina runtime, and user defined metrics.

getMetricsProvider

Retrieve metrics provider.

getMetricsReporter

Retrieve metrics reporter.

getSpanContext

Retrieve a map of span context data.

getTracingProvider

Retrieve tracer provider.

isMetricsEnabled

Check whether metrics is enabled.

isObservabilityEnabled

Check whether observability is enabled.

isTracingEnabled

Check whether tracing is enabled.

lookupMetric

Retrieve the specific metric that is described by the given name and tags.

startRootSpan

Start a span with no parent span.

startSpan

Start a span and create child relationship to current active span or user specified span.

Classes

[2]

Counter

This represents the metric type - counter, that can be only increased by an integer number.

Gauge

This represents the metric type - gauge, that can hold instantaneous, increased or decreased value during the usage.

Records

[4]

Metric

This represents the generic metric record that can represent both counter and gauge.

PercentileValue

This represents the percentile value record.

Snapshot

This represents the snapshot of the statistics calculation of the gauge.

StatisticConfig

This represents the statistic configuration that can be used to instatiate gauge metric.

Annotations

[1]

Observable

This is used for making a function observable.