Counter

Used to count how often something happens, say how often a certain button was pressed. A counter always starts from 0. Each time you record to a counter, its value is incremented. Unless incremented by a positive value, a counter will not be reported in pings, that means: the value 0 is never sent in a ping.

If you find that you need to control the actual value sent in the ping, you may be measuring something, not just counting something, and a Quantity metric may be a better choice.

Let the Glean metric do the counting

When using a counter metric, it is important to let the Glean metric do the counting. Using your own variable for counting and setting the counter yourself could be problematic because it will be difficult to reset the value at the exact moment that the value is sent in a ping. Instead, just use counter.add to increment the value and let Glean handle resetting the counter.

Recording API

add

Increases the counter by a certain amount. If no amount is passed it defaults to 1.

import org.mozilla.yourApplication.GleanMetrics.Controls

Controls.refreshPressed.add() // Adds 1 to the counter.
Controls.refreshPressed.add(5) // Adds 5 to the counter.
import org.mozilla.yourApplication.GleanMetrics.Controls;

Controls.INSTANCE.refreshPressed.add(); // Adds 1 to the counter.
Controls.INSTANCE.refreshPressed.add(5); // Adds 5 to the counter.
Controls.refreshPressed.add() // Adds 1 to the counter.
Controls.refreshPressed.add(5) // Adds 5 to the counter.
from glean import load_metrics
metrics = load_metrics("metrics.yaml")

metrics.controls.refresh_pressed.add()  # Adds 1 to the counter.
metrics.controls.refresh_pressed.add(5) # Adds 5 to the counter.
use glean_metrics;

controls::refresh_pressed.add(1); // Adds 1 to the counter.
controls::refresh_pressed.add(5); // Adds 5 to the counter.
import * as controls from "./path/to/generated/files/controls.js";

controls.refreshPressed.add(); // Adds 1 to the counter.
controls.refreshPressed.add(5); // Adds 5 to the counter.

C++

#include "mozilla/glean/GleanMetrics.h"

mozilla::glean::controls::refresh_pressed.Add(1);
mozilla::glean::controls::refresh_pressed.Add(5);

JavaScript

Glean.controls.refreshPressed.add(1);
Glean.controls.refreshPressed.add(5);

Recorded errors

  • invalid_value: If the counter is incremented by 0 or a negative value.

Limits

  • Only increments;
  • Saturates at the largest value that can be represented as a 32-bit signed integer (2147483647).

Testing API

testGetValue

Gets the recorded value for a given counter metric.

import org.mozilla.yourApplication.GleanMetrics.Controls

assertEquals(6, Controls.refreshPressed.testGetValue())
import org.mozilla.yourApplication.GleanMetrics.Controls;

assertEquals(6, Controls.INSTANCE.refreshPressed.testGetValue());
@testable import Glean

XCTAssertEqual(6, try Controls.refreshPressed.testGetValue())
from glean import load_metrics
metrics = load_metrics("metrics.yaml")

assert 6 == metrics.controls.refresh_pressed.test_get_value()

#![allow(unused)]
fn main() {
use glean_metrics;

assert_eq!(6, controls::refresh_pressed.test_get_value(None).unwrap());
}
import * as controls from "./path/to/generated/files/controls.js";

assert.strictEqual(6, await controls.refreshPressed.testGetValue());

C++

#include "mozilla/glean/GleanMetrics.h"

ASSERT_TRUE(mozilla::glean::controls::refresh_pressed.TestGetValue().isOk());
ASSERT_EQ(6, mozilla::glean::controls::refresh_pressed.TestGetValue().unwrap().value());

JavaScript

// testGetValue will throw NS_ERROR_LOSS_OF_SIGNIFICANT_DATA on error.
Assert.equal(6, Glean.controls.refreshPressed.testGetValue());

testHasValue

Whether or not any value was recorded for a given counter metric.

import org.mozilla.yourApplication.GleanMetrics.Controls

assertTrue(Controls.refreshPressed.testHasValue())
import org.mozilla.yourApplication.GleanMetrics.Controls;

assertTrue(Controls.INSTANCE.refreshPressed.testHasValue());
@testable import Glean

XCTAssert(Controls.refreshPressed.testHasValue())
from glean import load_metrics
metrics = load_metrics("metrics.yaml")

assert metrics.controls.refresh_pressed.test_has_value()

testGetNumRecordedErrors

Gets number of errors recorded for a given counter metric.

import org.mozilla.yourApplication.GleanMetrics.Controls

assertEquals(
    1, Controls.refreshPressed.testGetNumRecordedErrors(ErrorType.InvalidValue)
)
import org.mozilla.yourApplication.GleanMetrics.Controls;

assertEquals(
    1, Controls.INSTANCE.refreshPressed.testGetNumRecordedErrors(ErrorType.InvalidValue)
);
XCTAssertEqual(1, Controls.refreshPressed.testGetNumRecordedErrors(.invalidValue))
from glean import load_metrics
metrics = load_metrics("metrics.yaml")

from glean.testing import ErrorType

assert 1 == metrics.controls.refresh_pressed.test_get_num_recorded_errors(
    ErrorType.INVALID_VALUE
)

#![allow(unused)]
fn main() {
use glean::ErrorType;

use glean_metrics;

assert_eq!(
  1,
  controls::refresh_pressed.test_get_num_recorded_errors(
    ErrorType::InvalidValue
  )
);
}
import * as controls from "./path/to/generated/files/controls.js";
import { ErrorType } from "@mozilla/glean/<platform>";

assert.strictEqual(
  1,
  await controls.refreshPressed.testGetNumRecordedErrors(ErrorType.InvalidValue)
);

Metric parameters

Example counter metric definition:

controls:
  refresh_pressed:
    type: counter
    description: >
      Counts how often the refresh button is pressed.
    bugs:
      - https://bugzilla.mozilla.org/000000
    data_reviews:
      - https://bugzilla.mozilla.org/show_bug.cgi?id=000000#c3
    notification_emails:
      - me@mozilla.com
    expires: 2020-10-01

For a full reference on metrics parameters common to all metric types, refer to the metrics YAML registry format reference page.

Extra metric parameters

N/A

Data questions

  • How often was a certain button pressed?

Reference