package main

import (
	"fmt"
	"log/slog"
	"net/http"
	"net/http/httptest"
	_ "net/http/pprof" // mendaftarkan handler /debug/pprof/ ke DefaultServeMux
	"os"
	"runtime"
	"runtime/metrics"
	"strings"
)

// buangWaktu menjadikan log contoh ini deterministik.
func buangWaktu(groups []string, a slog.Attr) slog.Attr {
	if a.Key == slog.TimeKey {
		return slog.Attr{}
	}
	return a
}

// bacaMetrikUint64 membaca satu metrik runtime/metrics bertipe uint64.
func bacaMetrikUint64(nama string) uint64 {
	for _, deskripsi := range metrics.All() {
		if deskripsi.Name == nama {
			sampel := []metrics.Sample{{Name: nama}}
			metrics.Read(sampel)
			if sampel[0].Value.Kind() == metrics.KindUint64 {
				return sampel[0].Value.Uint64()
			}
		}
	}
	return 0
}

// susunLog membangun sekumpulan baris log menjadi satu buffer.
func susunLog(jumlahBaris int) string {
	var b strings.Builder
	for i := range jumlahBaris {
		fmt.Fprintf(&b, "req-%06d user=Budi status=200\n", i)
	}
	return b.String()
}

func main() {
	// Gauge konfigurasi: memastikan tuning GC yang aktif di production.
	fmt.Println("metrik /gc/gogc:percent =", bacaMetrikUint64("/gc/gogc:percent"))

	// Pemeriksaan endpoint pprof tanpa membuka port: permintaan disajikan
	// langsung ke DefaultServeMux memakai httptest.
	for _, path := range []string{"/debug/pprof/", "/debug/pprof/heap", "/debug/pprof/goroutine", "/debug/pprof/allocs"} {
		req := httptest.NewRequest(http.MethodGet, path, nil)
		rec := httptest.NewRecorder()
		http.DefaultServeMux.ServeHTTP(rec, req)
		fmt.Printf("GET %-22s -> %d (%s)\n", path, rec.Code, rec.Header().Get("Content-Type"))
	}

	// Laju alokasi: selisih metrik kumulatif sekitar beban kerja tetap.
	awal := bacaMetrikUint64("/gc/heap/allocs:bytes")
	bufferLog := susunLog(110_000)
	runtime.GC() // paksakan GC agar akuntansi alokasi diperbarui sebelum dibaca
	akhir := bacaMetrikUint64("/gc/heap/allocs:bytes")
	fmt.Println("panjang buffer log:", len(bufferLog), "byte")
	fmt.Println("laju alokasi 110 ribu baris log:", (akhir-awal)/1024/1024, "MiB")

	handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: buangWaktu})
	logger := slog.New(handler)
	logger.Info("diagnostik aktif", "endpoint", "/debug/pprof", "goroutine", runtime.NumGoroutine())
}
