# Metrics

> Everything you need to know to start exploring metrics with Last9.

Source: https://last9.io/docs/metrics/

## Sending Metrics to Last9

You can send a variety of metrics to Last9 from different sources:

- [Using OpenTelemetry](/docs/integrations/observability/opentelemetry/)
- [Prometheus remote write](/docs/integrations/observability/prometheus/)
- and, [other integrations](/docs/integrations/)

You can also view the list of integrations in the Last9 app under the [Metrics category on the Integrations screen](https://app.last9.io/integrations?category=metrics).

## Exploring Metrics

There are 3 primary ways of exploring metrics depending on your use case.

- **Metrics Explorer:** Use Last9's native UI for metrics with a guided Builder mode for filters, range, and aggregation, or a PromQL-compatible Code mode for advanced queries. Promote any query to a [dashboard](/docs/dashboards/) panel or turn it into an alert without rewriting it. [Learn more](/docs/metrics-explorer/).
- **Dashboards:** Build PromQL-powered panels and group them into reusable dashboards with variables and time controls. [Learn more](/docs/dashboards/).
- **Grafana:** For teams that prefer Grafana, use Last9's embedded Grafana instance against the same metrics backend.

## Alerting on Metrics

To create alerts on metrics, use [Alerting](/docs/alerting/). You can also turn any Metrics Explorer query into an alert directly from the results panel — see [Creating Alerts from Queries](/docs/metrics-explorer/#creating-alerts-from-queries).

:::tip[Metrics Alerts vs Log Alerts]
**Alert Studio** is for metrics-based alerts using PromQL. For log-based alerts using LogQL, use [Scheduled Search](/docs/scheduled-search/) instead.
:::

---

## Troubleshooting

- **Metric appears in Last9 but some labels are missing**

  If a metric is visible in Last9 but one or more labels are absent from the series, the most likely cause is that the label value was an **empty string** when the metric was recorded.

  Last9 follows the Prometheus data model: a label with an empty value is treated as if that label does not exist. The metric value is stored and queryable, but the label dimension is simply absent — no error is returned.

  This affects any instrumentation sending metrics via OTLP or Prometheus remote write, regardless of language.

  How to confirm: query the metric without any label filters and inspect the returned series. If a label you expect (e.g. `product_type`) is missing from some series but present on others, those series had an empty value for that label at record time.

  Fix: ensure the attribute value is non-empty before recording. Use a sentinel value like `"unknown"` if the value may not always be set:

  ```go
  // Go example — same principle applies to any language
  if productType == "" {
      productType = "unknown"
  }
  counter.Add(ctx, 1, otelmetric.WithAttributes(
      attribute.String("product_type", productType),
  ))
  ```

  ```python
  # Python example
  product_type = product_type or "unknown"
  counter.add(1, {"product_type": product_type})
  ```

  ```java
  // Java example
  String productType = rawProductType != null && !rawProductType.isEmpty()
      ? rawProductType : "unknown";
  counter.add(1, Attributes.of(AttributeKey.stringKey("product_type"), productType));
  ```

  For more detail on sending custom metrics via OpenTelemetry, see the [Go custom metrics guide](/docs/integrations/frameworks/go/custom-metrics/).

Please get in touch with us on [Discord](https://discord.com/invite/Q3p2EEucx9) or [Email](mailto:support@last9.io) if you have any questions.
