aboutsummaryrefslogtreecommitdiff
path: root/_content
diff options
context:
space:
mode:
authorCarlos Amedee <carlos@golang.org>2025-09-26 13:54:00 -0400
committerCarlos Amedee <carlos@golang.org>2025-09-26 11:10:34 -0700
commita03470fad8b53453eb564fad5403a98ef38bfcea (patch)
tree32aae04a003d9f4fbfd59ace3b3519bf6491f2d3 /_content
parentecea7cabd5cf3d5d71df54781e66cca93acfbe65 (diff)
downloadgo-x-website-a03470fad8b53453eb564fad5403a98ef38bfcea.tar.xz
_content/blog: fix markdown on flight recorder post
Change-Id: I7767342688f6d9a049659a79e5acb1d05e318276 Reviewed-on: https://go-review.googlesource.com/c/website/+/707175 Reviewed-by: Michael Pratt <mpratt@google.com> TryBot-Bypass: Carlos Amedee <carlos@golang.org> Commit-Queue: Carlos Amedee <carlos@golang.org> Reviewed-by: Alan Donovan <adonovan@google.com> Auto-Submit: Carlos Amedee <carlos@golang.org>
Diffstat (limited to '_content')
-rw-r--r--_content/blog/flight-recorder.md172
1 files changed, 86 insertions, 86 deletions
diff --git a/_content/blog/flight-recorder.md b/_content/blog/flight-recorder.md
index 115f794b..6c507d07 100644
--- a/_content/blog/flight-recorder.md
+++ b/_content/blog/flight-recorder.md
@@ -68,80 +68,80 @@ informing them if they guessed the right number. There is also a goroutine that,
minute, sends a report of all the guessed numbers to another service via an HTTP request.
{{raw `
-// bucket is a simple mutex-protected counter.
-type bucket struct {
- mu sync.Mutex
- guesses int
-}
+ // bucket is a simple mutex-protected counter.
+ type bucket struct {
+ mu sync.Mutex
+ guesses int
+ }
-func main() {
- // Make one bucket for each valid number a client could guess.
- // The HTTP handler will look up the guessed number in buckets by
- // using the number as an index into the slice.
- buckets := make([]bucket, 100)
+ func main() {
+ // Make one bucket for each valid number a client could guess.
+ // The HTTP handler will look up the guessed number in buckets by
+ // using the number as an index into the slice.
+ buckets := make([]bucket, 100)
- // Every minute, we send a report of how many times each number was guessed.
- go func() {
- for range time.Tick(1 * time.Minute) {
- sendReport(buckets)
- }
- }()
+ // Every minute, we send a report of how many times each number was guessed.
+ go func() {
+ for range time.Tick(1 * time.Minute) {
+ sendReport(buckets)
+ }
+ }()
- // Choose the number to be guessed.
- answer := rand.Intn(len(buckets))
+ // Choose the number to be guessed.
+ answer := rand.Intn(len(buckets))
- http.HandleFunc("/guess-number", func(w http.ResponseWriter, r *http.Request) {
- start := time.Now()
+ http.HandleFunc("/guess-number", func(w http.ResponseWriter, r *http.Request) {
+ start := time.Now()
- // Fetch the number from the URL query variable "guess" and convert it
- // to an integer. Then, validate it.
- guess, err := strconv.Atoi(r.URL.Query().Get("guess"))
- if err != nil || !(0 <= guess && guess < len(buckets)) {
- http.Error(w, "invalid 'guess' value", http.StatusBadRequest)
- return
- }
+ // Fetch the number from the URL query variable "guess" and convert it
+ // to an integer. Then, validate it.
+ guess, err := strconv.Atoi(r.URL.Query().Get("guess"))
+ if err != nil || !(0 <= guess && guess < len(buckets)) {
+ http.Error(w, "invalid 'guess' value", http.StatusBadRequest)
+ return
+ }
- // Select the appropriate bucket and safely increment its value.
- b := &buckets[guess]
- b.mu.Lock()
- b.guesses++
- b.mu.Unlock()
+ // Select the appropriate bucket and safely increment its value.
+ b := &buckets[guess]
+ b.mu.Lock()
+ b.guesses++
+ b.mu.Unlock()
- // Respond to the client with the guess and whether it was correct.
- fmt.Fprintf(w, "guess: %d, correct: %t", guess, guess == answer)
+ // Respond to the client with the guess and whether it was correct.
+ fmt.Fprintf(w, "guess: %d, correct: %t", guess, guess == answer)
- log.Printf("HTTP request: endpoint=/guess-number guess=%d duration=%s", guess, time.Since(start))
- })
- log.Fatal(http.ListenAndServe(":8090", nil))
-}
+ log.Printf("HTTP request: endpoint=/guess-number guess=%d duration=%s", guess, time.Since(start))
+ })
+ log.Fatal(http.ListenAndServe(":8090", nil))
+ }
-// sendReport posts the current state of buckets to a remote service.
-func sendReport(buckets []bucket) {
- counts := make([]int, len(buckets))
+ // sendReport posts the current state of buckets to a remote service.
+ func sendReport(buckets []bucket) {
+ counts := make([]int, len(buckets))
- for index := range buckets {
- b := &buckets[index]
- b.mu.Lock()
- defer b.mu.Unlock()
+ for index := range buckets {
+ b := &buckets[index]
+ b.mu.Lock()
+ defer b.mu.Unlock()
- counts[index] = b.guesses
- }
+ counts[index] = b.guesses
+ }
- // Marshal the report data into a JSON payload.
- b, err := json.Marshal(counts)
- if err != nil {
- log.Printf("failed to marshal report data: error=%s", err)
- return
- }
- url := "http://localhost:8091/guess-number-report"
- if _, err := http.Post(url, "application/json", bytes.NewReader(b)); err != nil {
- log.Printf("failed to send report: %s", err)
+ // Marshal the report data into a JSON payload.
+ b, err := json.Marshal(counts)
+ if err != nil {
+ log.Printf("failed to marshal report data: error=%s", err)
+ return
+ }
+ url := "http://localhost:8091/guess-number-report"
+ if _, err := http.Post(url, "application/json", bytes.NewReader(b)); err != nil {
+ log.Printf("failed to send report: %s", err)
+ }
}
-}
`}}
Here is the full code for the server:
-[https://go.dev/play/p/rX1eyKtVglF]/play/p/rX1eyKtVglF), and for a simple client:
+[https://go.dev/play/p/rX1eyKtVglF](/play/p/rX1eyKtVglF), and for a simple client:
[https://go.dev/play/p/2PjQ-1ORPiw](/play/p/2PjQ-1ORPiw). To avoid a third
process, the "client" also implements the report server, though in a real system this would
be separate.
@@ -170,12 +170,12 @@ we see the first response exceeding 100 milliseconds.
First, in `main`, we'll configure and start the flight recorder:
{{raw `
-// Set up the flight recorder
-fr := trace.NewFlightRecorder(trace.FlightRecorderConfig{
- MinAge: 200 * time.Millisecond,
- MaxBytes: 1 << 20, // 1 MiB
-})
-fr.Start()
+ // Set up the flight recorder
+ fr := trace.NewFlightRecorder(trace.FlightRecorderConfig{
+ MinAge: 200 * time.Millisecond,
+ MaxBytes: 1 << 20, // 1 MiB
+ })
+ fr.Start()
`}}
`MinAge` configures the duration for which trace data is reliably retained, and we
@@ -188,31 +188,31 @@ or 10 MB/s for a busy service.
Next, we'll add a helper function to capture the snapshot and write it to a file:
{{raw `
-var once sync.Once
+ var once sync.Once
-// captureSnapshot captures a flight recorder snapshot.
-func captureSnapshot(fr *trace.FlightRecorder) {
- // once.Do ensures that the provided function is executed only once.
- once.Do(func() {
- f, err := os.Create("snapshot.trace")
- if err != nil {
- log.Printf("opening snapshot file %s failed: %s", f.Name(), err)
- return
- }
- defer f.Close() // ignore error
+ // captureSnapshot captures a flight recorder snapshot.
+ func captureSnapshot(fr *trace.FlightRecorder) {
+ // once.Do ensures that the provided function is executed only once.
+ once.Do(func() {
+ f, err := os.Create("snapshot.trace")
+ if err != nil {
+ log.Printf("opening snapshot file %s failed: %s", f.Name(), err)
+ return
+ }
+ defer f.Close() // ignore error
- // WriteTo writes the flight recorder data to the provided io.Writer.
- _, err = fr.WriteTo(f)
- if err != nil {
- log.Printf("writing snapshot to file %s failed: %s", f.Name(), err)
- return
- }
+ // WriteTo writes the flight recorder data to the provided io.Writer.
+ _, err = fr.WriteTo(f)
+ if err != nil {
+ log.Printf("writing snapshot to file %s failed: %s", f.Name(), err)
+ return
+ }
- // Stop the flight recorder after the snapshot has been taken.
- fr.Stop()
- log.Printf("captured a flight recorder snapshot to %s", f.Name())
- })
-}
+ // Stop the flight recorder after the snapshot has been taken.
+ fr.Stop()
+ log.Printf("captured a flight recorder snapshot to %s", f.Name())
+ })
+ }
`}}
And finally, just before logging a completed request, we'll trigger the snapshot if the request