Go-фича: Метрики горутин

Часть серии Принято! В ней простыми словами объясняются новые фичи Go.

Подробные метрики горутин от рантайма.

Версия 1.26 • Станд. библиотека • Полезно

Что

Новые метрики в пакете runtime/metrics позволяют лучше понять, как работают горутины:

  • Общее количество горутин с начала работы программы.
  • Количество горутин в каждом состоянии.
  • Количество активных потоков.

Зачем

Пакет runtime/metrics уже предоставляет много информации о работе программы, но в нем не хватало метрик по состояниям горутин и количеству потоков.

Метрики по состояниям горутин помогают находить типичные проблемы в продакшене. Например, если растет число горутин в состоянии waiting, это может указывать на проблемы с блокировками. Много горутин в состоянии not-in-go — значит, они застряли в системных вызовах или cgo. Если увеличивается очередь runnable — CPU не справляются с нагрузкой.

Системы мониторинга могут отслеживать эти показатели, чтобы замечать ухудшения и отправлять оповещения, если поведение горутин меняется. Разработчики могут использовать метрики, чтобы раньше обнаруживать проблемы, не прибегая к полным трассировкам.

Как

Добавить следующие метрики в пакет runtime/metrics:

/sched/goroutines-created:goroutines
	Общее количество горутин, запущенных
    с момент старта приложения (накопительный итог).

/sched/goroutines/not-in-go:goroutines
	Примерное количество горутин, которые
    «ушли» в системный или cgo-вызов.

/sched/goroutines/runnable:goroutines
	Примерное количество горутин, которые готовы
    к выполнению, но пока не выполняются.

/sched/goroutines/running:goroutines
	Примерное количество выполняющихся горутин.
    Всегда меньше или равно /sched/gomaxprocs:threads.

/sched/goroutines/waiting:goroutines
	Примерное количество горутин, ожидающих
    на ресурсе (I/O или примитивы синхронизации).

/sched/threads/total:threads
	Текущее количество активных потоков,
    которыми управляет планировщик Go.

Сумма значений показателей по каждому состоянию не обязательно равна общему количеству активных горутин (метрика /sched/goroutines:goroutines, доступна в Go 1.16+).

Все метрики используют счетчики типа uint64.

Пример

Запускаем несколько горутин и выводим метрики через 100 мс работы:

func main() {
	go work() // omitted for brevity
	time.Sleep(100 * time.Millisecond)

	fmt.Println("Goroutine metrics:")
	printMetric("/sched/goroutines-created:goroutines", "Created")
	printMetric("/sched/goroutines:goroutines", "Live")
	printMetric("/sched/goroutines/not-in-go:goroutines", "Syscall/CGO")
	printMetric("/sched/goroutines/runnable:goroutines", "Runnable")
	printMetric("/sched/goroutines/running:goroutines", "Running")
	printMetric("/sched/goroutines/waiting:goroutines", "Waiting")

	fmt.Println("Thread metrics:")
	printMetric("/sched/gomaxprocs:threads", "Max")
	printMetric("/sched/threads/total:threads", "Live")
}

func printMetric(name string, descr string) {
	sample := []metrics.Sample{{Name: name}}
	metrics.Read(sample)
    // Предполагаем, что значение типа uint64; так делать в продакшене не стоит.
    // Лучше действовать в соответствии с sample[0].Value.Kind.
	fmt.Printf("  %s: %v\n", descr, sample[0].Value.Uint64())
}
Goroutine metrics:
  Created: 52
  Live: 12
  Syscall/CGO: 0
  Runnable: 0
  Running: 4
  Waiting: 8
Thread metrics:
  Max: 8
  Live: 4

Никаких сюрпризов: новые значения метрик читаем так же, как и раньше — с помощью metrics.Read.

Ссылки

𝗣 15490 • 𝗖𝗟 690397, 690398, 690399

★ Подписывайтесь на канал и проходите курсы.