| 456 | } |
| 457 | |
| 458 | func blockProfiling(ctx context.Context, interval time.Duration) { |
| 459 | ticker := time.NewTicker(interval) |
| 460 | defer ticker.Stop() |
| 461 | numGoroutines.Add(1) |
| 462 | defer numGoroutines.Add(-1) |
| 463 | for { |
| 464 | select { |
| 465 | case <-ctx.Done(): |
| 466 | return |
| 467 | case <-ticker.C: |
| 468 | fileName := fmt.Sprintf("block-%s.prof", time.Now().Format(time.RFC3339)) |
| 469 | blockProfBuf := bytes.Buffer{} |
| 470 | runtime.SetBlockProfileRate(1) |
| 471 | time.Sleep(interval) |
| 472 | err := pprof.Lookup("block").WriteTo(&blockProfBuf, 0) |
| 473 | if err != nil { |
| 474 | log.Printf("Error writing block profile: %v", err) |
| 475 | return |
| 476 | } |
| 477 | runtime.SetBlockProfileRate(0) |
| 478 | |
| 479 | err = os.WriteFile(fileName, blockProfBuf.Bytes(), os.ModePerm) |
| 480 | if err != nil { |
| 481 | log.Printf("Error writing block profile to file: %v", err) |
| 482 | return |
| 483 | } |
| 484 | } |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | func goroutineProfiling(ctx context.Context, interval time.Duration) { |
| 489 | ticker := time.NewTicker(interval) |