|
| 1 | +<script lang="ts"> |
| 2 | + import { posts, type post } from '../posts'; |
| 3 | + import PageSubtitle from '../../../../components/pageSubtitle.svelte'; |
| 4 | + import PageLayout from '../../../../components/layout/pageLayout.svelte'; |
| 5 | + import PageHeader from '../../../../components/pageHeader.svelte'; |
| 6 | + import PageParagraph from '../../../../components/pageParagraph.svelte'; |
| 7 | + import { base } from '$app/paths'; |
| 8 | + import Code from '../../../../components/code.svelte'; |
| 9 | +
|
| 10 | + let p: post = posts[9]; // 0 based post 10 |
| 11 | + let title = p.title; |
| 12 | + let date = p.date; |
| 13 | + let backText = 'blog'; |
| 14 | + let backHref = '/blog'; |
| 15 | +
|
| 16 | + let debugMux = ` |
| 17 | +import ( |
| 18 | + "net/http" |
| 19 | + "net/http/pprof" |
| 20 | +
|
| 21 | + "github.com/arl/statsviz" |
| 22 | +) |
| 23 | +
|
| 24 | +func Mux() *http.ServeMux { |
| 25 | + mux := http.NewServeMux() |
| 26 | +
|
| 27 | + mux.HandleFunc("/debug/pprof/", pprof.Index) |
| 28 | + mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) |
| 29 | + mux.HandleFunc("/debug/pprof/profile", pprof.Profile) |
| 30 | + mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) |
| 31 | + mux.HandleFunc("/debug/pprof/trace", pprof.Trace) |
| 32 | +
|
| 33 | + statsviz.Register(mux) |
| 34 | +
|
| 35 | + // Liveness handler |
| 36 | + mux.HandleFunc("/liveness", func(w http.ResponseWriter, r *http.Request) { |
| 37 | + // simulate IO work |
| 38 | + time.Sleep(time.Millisecond * 10) |
| 39 | + fmt.Fprintln(w, "OK") |
| 40 | + }) |
| 41 | +
|
| 42 | + return mux |
| 43 | +} |
| 44 | +`; |
| 45 | +
|
| 46 | + let serve = ` |
| 47 | +func main() { |
| 48 | + if err := http.ListenAndServe("0.0.0.0:3010", Mux()); err != nil { |
| 49 | + fmt.Println("Server Error") |
| 50 | + } |
| 51 | +} |
| 52 | +`; |
| 53 | +</script> |
| 54 | + |
| 55 | +<PageLayout {backHref} {backText} {title} {date}> |
| 56 | + <PageSubtitle className="underline underline-offset-8 decoration-sky-500 capitalize" |
| 57 | + >How to Use Go’s Built-In Profiling Tools to Monitor and Debug Your Services</PageSubtitle |
| 58 | + > |
| 59 | + |
| 60 | + <img src="{base}/blog/10/statsviz.png" alt="cert" /> |
| 61 | + |
| 62 | + <PageParagraph> |
| 63 | + In this post, we’ll walk through setting up debug endpoints to profile your Go application in |
| 64 | + real time. We'll also integrate <a href="https://github.com/arl/statsviz" class="text-sky-500" |
| 65 | + >Statsviz</a |
| 66 | + > to provide a user-friendly GUI for visualizing metrics like heap usage and goroutine activity. |
| 67 | + To make things more interesting, we’ll simulate load by sending a burst of requests to a liveness |
| 68 | + endpoint, allowing us to see how the heap and goroutine count respond under pressure. |
| 69 | + </PageParagraph> |
| 70 | + |
| 71 | + <PageParagraph> |
| 72 | + The first step is to register the pprof debug endpoints with your Go HTTP server. These handlers |
| 73 | + expose runtime profiling data such as heap usage, goroutines, CPU profiles, and more. Go |
| 74 | + provides this functionality through the net/http/pprof package, which can be easily integrated |
| 75 | + into your server. We’ll also hook in the Statsviz package to enhance this setup with a |
| 76 | + real-time, browser-based dashboard for visualizing metrics. |
| 77 | + </PageParagraph> |
| 78 | + |
| 79 | + <Code code={debugMux} lang="go"></Code> |
| 80 | + <PageParagraph> |
| 81 | + With your handlers configured, the next step is simply to serve them using Go’s built-in HTTP |
| 82 | + server: |
| 83 | + </PageParagraph> |
| 84 | + |
| 85 | + <Code code={serve} lang="go"></Code> |
| 86 | + |
| 87 | + <PageParagraph> |
| 88 | + Next, we'll simulate a burst of traffic using the following command. This will send 100 |
| 89 | + concurrent request to the liveness endpoint. |
| 90 | + </PageParagraph> |
| 91 | + |
| 92 | + <Code code={serve} lang="go"></Code> |
| 93 | + |
| 94 | + <PageParagraph> |
| 95 | + Heap free: is that is free memory that could be returned to the OS, but has not been. Heap |
| 96 | + released: is memory that is free memory that has been returned to the OS. |
| 97 | + </PageParagraph> |
| 98 | + <PageParagraph>Before burst graph:</PageParagraph> |
| 99 | + |
| 100 | + <img src="{base}/blog/10/heap-graphs.png" alt="heap graphs" /> |
| 101 | + <img src="{base}/blog/10/heap-details.png" alt="heap details" /> |
| 102 | + <img src="{base}/blog/10/heap-global.png" alt="heap global" /> |
| 103 | + <img src="{base}/blog/10/goroutines.png" alt="goroutines" /> |
| 104 | + |
| 105 | + <p> |
| 106 | + <a |
| 107 | + target="_blank" |
| 108 | + class="text-sky-500" |
| 109 | + href="https://www.ardanlabs.com/training/individual-on-demand/ultimate-go-bundle/">Courses</a |
| 110 | + > |
| 111 | + </p> |
| 112 | +</PageLayout> |
0 commit comments