Prometheus метрики в Swift: интеграция для iOS/macOS приложений

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Prometheus метрики в Swift (iOS/macOS): мониторинг мобильных и десктопных приложений

Prometheus — это система мониторинга и оповещения с открытым исходным кодом, которая собирает метрики в виде временных рядов. В экосистеме Apple (iOS и macOS) использование Prometheus позволяет отслеживать производительность приложений, поведение пользователей, состояние сети и другие важные показатели. В этой статье мы рассмотрим, как внедрить Prometheus метрики в Swift-проекты, какие библиотеки для этого существуют и как настроить экспорт данных.

Зачем нужны Prometheus метрики в мобильных приложениях?

Мобильные и десктопные приложения часто работают в условиях ограниченных ресурсов и нестабильного соединения. Сбор метрик помогает:

  • Выявлять узкие места производительности (задержки UI, утечки памяти)
  • Отслеживать частоту и типы ошибок (crash, network errors)
  • Анализировать пользовательское поведение (время сессии, экраны)
  • Настраивать алерты на критические значения (например, время ответа API > 5 сек)

Основные типы метрик Prometheus

Prometheus поддерживает четыре основных типа метрик, которые можно реализовать в Swift:

  • Counter (счётчик) — монотонно возрастающее значение (количество запросов, ошибок)
  • Gauge (датчик) — произвольное значение, которое может увеличиваться и уменьшаться (текущая память, активные пользователи)
  • Histogram (гистограмма) — распределение значений по заданным интервалам (время выполнения функций)
  • Summary (суммарий) — распределение с квантилями (задержки)

Библиотеки для Swift

На данный момент наиболее популярная библиотека для работы с Prometheus в Swift — SwiftPrometheus. Она предоставляет простой API для создания и регистрации метрик, а также поддерживает экспорт в формате, совместимом с Prometheus.

Установка через Swift Package Manager:

// Package.swift
dependencies: [
    .package(url: "https://github.com/reddavis/SwiftPrometheus.git", from: "1.0.0")
]

Примеры кода на Swift

1. Создание счётчика запросов к API

import SwiftPrometheus

let prometheus = Prometheus()
let apiRequests = prometheus.createCounter(
    named: "api_requests_total",
    help: "Total number of API requests",
    labels: ["endpoint"]
)

// Инкремент при каждом запросе
apiRequests.inc(["endpoint": "/users"])
apiRequests.inc(["endpoint": "/posts"])

2. Gauge для отслеживания памяти

let memoryGauge = prometheus.createGauge(
    named: "app_memory_bytes",
    help: "Current memory usage in bytes"
)

// Обновление при изменении памяти
memoryGauge.set(Double(reportMemoryUsage()))

3. Гистограмма времени загрузки данных

let loadDuration = prometheus.createHistogram(
    named: "data_load_duration_seconds",
    help: "Histogram of data loading time",
    buckets: [0.1, 0.5, 1.0, 2.0, 5.0]
)

let start = CFAbsoluteTimeGetCurrent()
// ... загрузка данных
let elapsed = CFAbsoluteTimeGetCurrent() - start
loadDuration.observe(elapsed)

Экспорт метрик в Prometheus

Чтобы Prometheus мог собирать метрики, ваше приложение должно предоставить эндпоинт, возвращающий данные в текстовом формате (plain text exposition format). Для iOS/macOS это можно сделать через локальный HTTP-сервер (например, используя Network.framework или сторонние библиотеки).

Пример простого HTTP-сервера для экспорта:

import SwiftPrometheus
import Network

class MetricsServer {
    let prometheus: Prometheus
    var listener: NWListener?
    
    init(prometheus: Prometheus, port: UInt16 = 9090) {
        self.prometheus = prometheus
        startServer(port: port)
    }
    
    private func startServer(port: UInt16) {
        let params = NWParameters.tcp
        listener = try? NWListener(using: params, on: NWEndpoint.Port(rawValue: port)!)
        listener?.newConnectionHandler = { [weak self] connection in
            connection.start(queue: .global())
            self?.handleConnection(connection)
        }
        listener?.start(queue: .global())
    }
    
    private func handleConnection(_ connection: NWConnection) {
        // Формируем ответ с метриками в формате Prometheus
        let metricsText = prometheus.outputString()
        let response = """
        HTTP/1.1 200 OK
        Content-Type: text/plain; charset=utf-8
        Content-Length: \(metricsText.utf8.count)
        
        \(metricsText)
        """
        connection.send(content: response.data(using: .utf8), completion: .contentProcessed({ _ in
            connection.cancel()
        }                    

Рекомендаций