diff options
| author | Carlos Amedee <carlos@golang.org> | 2025-09-26 13:54:00 -0400 |
|---|---|---|
| committer | Carlos Amedee <carlos@golang.org> | 2025-09-26 11:10:34 -0700 |
| commit | a03470fad8b53453eb564fad5403a98ef38bfcea (patch) | |
| tree | 32aae04a003d9f4fbfd59ace3b3519bf6491f2d3 /_content | |
| parent | ecea7cabd5cf3d5d71df54781e66cca93acfbe65 (diff) | |
| download | go-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.md | 172 |
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 |
