Skip to content

Commit b364d68

Browse files
wip: post 10
1 parent a0b25b0 commit b364d68

File tree

7 files changed

+118
-0
lines changed

7 files changed

+118
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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>

src/routes/(main)/blog/posts.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,11 @@ export const posts: post[] = [
5858
title: 'Completed Ultimate Go Language Guide Course',
5959
description: `After completing the course, I deepened my understanding of writing efficient, idiomatic Go code. I explored Go internals, learned to balance readability and performance, and focused on package-oriented design for better maintainability and long-term success.`,
6060
date: '2025-04-07'
61+
},
62+
{
63+
id: '10',
64+
title: 'Exposing Go Internals: Setting Up Debug Endpoints',
65+
description: `In this post, we’ll walk through setting up debug endpoints to profile your Go application in real time. We'll also integrate Statsviz to provide a user-friendly GUI for visualizing metrics like heap usage and goroutine activity. To make things more interesting, we’ll simulate load by sending a burst of requests to a liveness endpoint, allowing us to see how the heap and goroutine count respond under pressure.`,
66+
date: '2025-04-15'
6167
}
6268
];

static/blog/10/goroutines.png

27 KB
Loading

static/blog/10/heap-details.png

37.3 KB
Loading

static/blog/10/heap-global.png

42 KB
Loading

static/blog/10/heap-graphs.png

186 KB
Loading

static/blog/10/statsviz.png

228 KB
Loading

0 commit comments

Comments
 (0)