Nenhuma descrição

main.go 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package main
  2. import (
  3. "crypto/md5"
  4. "encoding/hex"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. _ "net/http/pprof"
  9. "os"
  10. "github.com/gin-gonic/gin"
  11. "github.com/google/pprof/pkg/driver"
  12. "github.com/google/pprof/profile"
  13. "github.com/sirupsen/logrus"
  14. )
  15. func main() {
  16. r := gin.Default()
  17. r.Static("/", "html")
  18. r.POST("/upload", upload)
  19. r.GET("/pprof/:hash/:method", mapping)
  20. r.Run(":8090")
  21. }
  22. func mapping(c *gin.Context) {
  23. hash := c.Param("hash")
  24. if hash == "" {
  25. c.AbortWithStatus(http.StatusNotFound)
  26. return
  27. }
  28. filename := fmt.Sprintf("%s.pprof", hash)
  29. f, err := os.OpenFile(filename, os.O_RDONLY, os.ModePerm)
  30. if err != nil {
  31. c.AbortWithError(http.StatusInternalServerError, err)
  32. return
  33. }
  34. defer f.Close()
  35. prof, err := profile.Parse(f)
  36. if err != nil {
  37. c.AbortWithError(http.StatusInternalServerError, err)
  38. return
  39. }
  40. ui, err := driver.MakeWebInterface(prof, nil)
  41. if err != nil {
  42. c.AbortWithError(http.StatusInternalServerError, err)
  43. return
  44. }
  45. method := c.Param("method")
  46. switch method {
  47. case "", "dot":
  48. ui.Dot(c.Writer, c.Request)
  49. case "top":
  50. ui.Top(c.Writer, c.Request)
  51. case "disasm":
  52. ui.Disasm(c.Writer, c.Request)
  53. case "source":
  54. ui.Source(c.Writer, c.Request)
  55. case "peek":
  56. ui.Peek(c.Writer, c.Request)
  57. case "flamegraph":
  58. ui.Flamegraph(c.Writer, c.Request)
  59. case "saveconfig":
  60. ui.SaveConfig(c.Writer, c.Request)
  61. case "deleteconfig":
  62. ui.DeleteConfig(c.Writer, c.Request)
  63. default:
  64. c.AbortWithStatus(http.StatusNotFound)
  65. }
  66. }
  67. func upload(c *gin.Context) {
  68. f, _, err := c.Request.FormFile("file")
  69. if err != nil {
  70. logrus.Errorln("upload file error:", err)
  71. c.AbortWithError(http.StatusInternalServerError, err)
  72. return
  73. }
  74. fdata, _ := ioutil.ReadAll(f)
  75. f.Close()
  76. rhash := hash(fdata)
  77. if fileExist(rhash) { // 文件已存在
  78. c.Redirect(http.StatusFound, fmt.Sprintf("/pprof/%s/flamegraph", rhash))
  79. return
  80. }
  81. fileDst := fmt.Sprintf("%s.pprof", rhash)
  82. file, err := os.Create(fileDst)
  83. if err != nil {
  84. c.AbortWithError(http.StatusInternalServerError, err)
  85. return
  86. }
  87. defer file.Close()
  88. if _, err := file.Write(fdata); err != nil {
  89. c.AbortWithError(http.StatusInternalServerError, err)
  90. return
  91. }
  92. c.JSONP(http.StatusOK, map[string]interface{}{
  93. "code": 0,
  94. "msg": "ok",
  95. "data": rhash,
  96. })
  97. }
  98. func hash(data []byte) string {
  99. h := md5.New()
  100. h.Write(data)
  101. return hex.EncodeToString(h.Sum(nil))
  102. }
  103. func fileExist(file string) bool {
  104. return false
  105. }