GoDasturchi
Metrics & Observability: Implementation (Part 2)

Metrics & Observability: Implementation (Part 2)

Metrikalar va kuzatuvchanlik: amalga oshirish (2-qism)

Endi oldingi darsda ko'rgan "Counter" g'oyasini haqiqiy Go kodida yozamiz. Buni ombordagi sanoq taxtasiga o'xshating: har safar mahsulot sotilganda, kimdir taxtaga bitta chiziqcha qo'shadi — kuni oxirida chiziqchalarni sanab, nechta sotilganini bilib olish mumkin.

example.go
package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

type Counter struct {
	value int64
}

func (c *Counter) Inc() { atomic.AddInt64(&c.value, 1) }
func (c *Counter) Value() int64 { return atomic.LoadInt64(&c.value) }

// Metrics — turli nomdagi hisoblagichlarni saqlaydigan markaz
type Metrics struct {
	mu       sync.Mutex
	counters map[string]*Counter
}

func NewMetrics() *Metrics {
	return &Metrics{counters: make(map[string]*Counter)}
}

func (m *Metrics) Counter(name string) *Counter {
	m.mu.Lock()
	defer m.mu.Unlock()
	if m.counters[name] == nil {
		m.counters[name] = &Counter{}
	}
	return m.counters[name]
}

func main() {
	metrics := NewMetrics()
	metrics.Counter("requests_total").Inc()
	metrics.Counter("requests_total").Inc()
	metrics.Counter("errors_total").Inc()

	fmt.Println(metrics.Counter("requests_total").Value())
	fmt.Println(metrics.Counter("errors_total").Value())
}

Counter — "Atomic Operations" darsida (Data Structures in Go kursida) ko'rgan atomic.AddInt64ning aynan o'zi: bu bir nechta goroutine bir vaqtda hisoblagichni oshirsa ham (masalan minglab bir vaqtdagi HTTP so'rovi), natija hech qachon noto'g'ri bo'lmasligini ta'minlaydi. Metrics esa turli nomdagi hisoblagichlarni (requests_total, errors_total) bitta markazda saqlaydi — Counter(name) chaqirilganda, agar shu nomli hisoblagich hali yo'q bo'lsa, uni avtomatik yaratadi ("Make Zero Values Useful" darsida ko'rgan dangasa ishga tushirish naqshi).

Haqiqiy production kodida bu qo'lda yozilgan Metrics o'rniga github.com/prometheus/client_golang kabi tayyor kutubxona ishlatiladi (u qo'shimcha ravishda HTTP orqali metrikalarni "chiqarish" imkonini ham beradi, Prometheus tizimi ularni "yig'ib olishi" uchun), lekin ularning ichki g'oyasi — atomik hisoblagichlar to'plami — aynan shu yerda ko'rgan tamoyilning o'zi.

>_ Exercise

Metrics'ga Gauge (ko'tarilishi ham, tushishi ham mumkin bo'lgan qiymat) qo'shing.

  • Gauge struct'ini yozing: Inc() va Dec() metodlari bilan (atomic.AddInt64 bilan +1 va -1)
  • Value() int64 metodini qo'shing
  • Gauge yarating, 3 marta Inc(), 1 marta Dec() qiling, Value()ni chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Counter va Gauge'ning ichki tuzilishi bir xil (atomik butun son), farqi faqat semantikada: Counter faqat oshadi, Gauge esa ikkala yo'nalishda ham o'zgarishi mumkin.

NEXT UP

Secrets Management

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Metrics & Observability: Implementation (Part 2)

Metrikalar va kuzatuvchanlik: amalga oshirish (2-qism)

Endi oldingi darsda ko'rgan "Counter" g'oyasini haqiqiy Go kodida yozamiz. Buni ombordagi sanoq taxtasiga o'xshating: har safar mahsulot sotilganda, kimdir taxtaga bitta chiziqcha qo'shadi — kuni oxirida chiziqchalarni sanab, nechta sotilganini bilib olish mumkin.

example.go
package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

type Counter struct {
	value int64
}

func (c *Counter) Inc() { atomic.AddInt64(&c.value, 1) }
func (c *Counter) Value() int64 { return atomic.LoadInt64(&c.value) }

// Metrics — turli nomdagi hisoblagichlarni saqlaydigan markaz
type Metrics struct {
	mu       sync.Mutex
	counters map[string]*Counter
}

func NewMetrics() *Metrics {
	return &Metrics{counters: make(map[string]*Counter)}
}

func (m *Metrics) Counter(name string) *Counter {
	m.mu.Lock()
	defer m.mu.Unlock()
	if m.counters[name] == nil {
		m.counters[name] = &Counter{}
	}
	return m.counters[name]
}

func main() {
	metrics := NewMetrics()
	metrics.Counter("requests_total").Inc()
	metrics.Counter("requests_total").Inc()
	metrics.Counter("errors_total").Inc()

	fmt.Println(metrics.Counter("requests_total").Value())
	fmt.Println(metrics.Counter("errors_total").Value())
}

Counter — "Atomic Operations" darsida (Data Structures in Go kursida) ko'rgan atomic.AddInt64ning aynan o'zi: bu bir nechta goroutine bir vaqtda hisoblagichni oshirsa ham (masalan minglab bir vaqtdagi HTTP so'rovi), natija hech qachon noto'g'ri bo'lmasligini ta'minlaydi. Metrics esa turli nomdagi hisoblagichlarni (requests_total, errors_total) bitta markazda saqlaydi — Counter(name) chaqirilganda, agar shu nomli hisoblagich hali yo'q bo'lsa, uni avtomatik yaratadi ("Make Zero Values Useful" darsida ko'rgan dangasa ishga tushirish naqshi).

Haqiqiy production kodida bu qo'lda yozilgan Metrics o'rniga github.com/prometheus/client_golang kabi tayyor kutubxona ishlatiladi (u qo'shimcha ravishda HTTP orqali metrikalarni "chiqarish" imkonini ham beradi, Prometheus tizimi ularni "yig'ib olishi" uchun), lekin ularning ichki g'oyasi — atomik hisoblagichlar to'plami — aynan shu yerda ko'rgan tamoyilning o'zi.

>_ Exercise

Metrics'ga Gauge (ko'tarilishi ham, tushishi ham mumkin bo'lgan qiymat) qo'shing.

  • Gauge struct'ini yozing: Inc() va Dec() metodlari bilan (atomic.AddInt64 bilan +1 va -1)
  • Value() int64 metodini qo'shing
  • Gauge yarating, 3 marta Inc(), 1 marta Dec() qiling, Value()ni chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Counter va Gauge'ning ichki tuzilishi bir xil (atomik butun son), farqi faqat semantikada: Counter faqat oshadi, Gauge esa ikkala yo'nalishda ham o'zgarishi mumkin.

NEXT UP

Secrets Management