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

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

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

Начать курс

Prometheus метрики в Swift (iOS/macOS)

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

Что такое SwiftPrometheus?

SwiftPrometheus — это клиентская библиотека для Swift, реализующая спецификацию Prometheus. Она позволяет создавать три основных типа метрик: Counter (счётчик), Gauge (измеритель) и Histogram (гистограмма). Библиотека полностью написана на Swift, поддерживает iOS 13+, macOS 10.15+, watchOS 6+ и tvOS 13+.

Установка

Добавьте зависимость в ваш Package.swift:

// swift-tools-version:5.5
import PackageDescription

let package = Package(
    name: "MyApp",
    dependencies: [
        .package(url: "https://github.com/QuickBirdEng/SwiftPrometheus.git", from: "2.0.0")
    ],
    targets: [
        .target(
            name: "MyApp",
            dependencies: ["SwiftPrometheus"]
        )
    ]
)

Или через CocoaPods в Podfile:

pod 'SwiftPrometheus', '~> 2.0'

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

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

Пример использования Counter

import SwiftPrometheus

let prometheus = Prometheus()
let httpRequests = prometheus.createCounter(for: "http_requests_total",
                                            help: "Total number of HTTP requests",
                                            labels: ["method", "path"])

httpRequests.inc() // +1
httpRequests.inc(5) // +5
httpRequests.labels(["GET", "/api/v1/users"]).inc() // с метками

Пример использования Gauge

let temperature = prometheus.createGauge(for: "device_temperature_celsius",
                                         help: "Current device temperature")

temperature.set(36.5) // установить значение
temperature.inc(2.0)  // увеличить на 2
temperature.dec(1.0)  // уменьшить на 1

Пример использования Histogram

let requestDuration = prometheus.createHistogram(for: "request_duration_seconds",
                                                help: "Request duration in seconds",
                                                buckets: [0.1, 0.5, 1.0, 2.5, 5.0])

requestDuration.observe(0.3) // запись значения

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

Для экспорта создайте HTTP endpoint, который будет отдавать метрики в текстовом формате. Пример для Vapor (серверная сторона):

import Vapor
import SwiftPrometheus

func routes(_ app: Application) throws {
    app.get("metrics") { req in
        let metrics = prometheus.collect()
        return Response(body: .init(string: metrics))
    }
}

Для iOS/macOS приложений можно использовать встроенный URLSession для отправки метрик на сервер Prometheus:

func sendMetrics() {
    let metrics = prometheus.collect()
    var request = URLRequest(url: URL(string: "https://pushgateway.example.org/metrics")!)
    request.httpMethod = "POST"
    request.httpBody = metrics.data(using: .utf8)
    URLSession.shared.dataTask(with: request).resume()
}

Дополнительные возможности

  • Метки (labels) — позволяют добавлять размерности к метрикам.
  • Кастомные коллекторы — возможность собирать метрики из системных источников (например, память, CPU).
  • Pushgateway — для отправки метрик даже при временном отсутствии сервера.

Практический пример: мониторинг сетевых запросов

class NetworkMonitor {
    private let requestCounter: Counter
    
    init(prometheus: Prometheus) {
        requestCounter = prometheus.createCounter(
            for: "network_requests_total",
            help: "Total network requests",
            labels: ["status"]
        )
    }
    
    func trackRequest(statusCode: Int) {
        let statusGroup = statusCode < 400 ? "success" : "error"
        requestCounter.labels([statusGroup]).inc()
    }
}

// Использование
let monitor = NetworkMonitor(prometheus: prometheus)
monitor.trackRequest(statusCode: 200)
monitor.trackRequest(statusCode: 500)

Заключение

Б

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