status.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Implementation of GetDetailedStatus API
  2. // This feature is designed to address Issue #850, providing Nginx load monitoring functionality similar to BT Panel
  3. // Returns detailed Nginx status information, including request statistics, connections, worker processes, and other data
  4. package nginx
  5. import (
  6. "errors"
  7. "net/http"
  8. "strings"
  9. "time"
  10. "github.com/0xJacky/Nginx-UI/internal/nginx"
  11. "github.com/0xJacky/Nginx-UI/internal/performance"
  12. "github.com/gin-gonic/gin"
  13. "github.com/uozi-tech/cosy"
  14. "github.com/uozi-tech/cosy/logger"
  15. )
  16. // NginxPerformanceInfo stores Nginx performance-related information
  17. type NginxPerformanceInfo struct {
  18. // Basic status information
  19. performance.StubStatusData
  20. // Process-related information
  21. performance.NginxProcessInfo
  22. // Configuration information
  23. performance.NginxConfigInfo
  24. }
  25. // GetDetailStatus retrieves detailed Nginx status information
  26. func GetDetailStatus(c *gin.Context) {
  27. response := performance.GetPerformanceData()
  28. c.JSON(http.StatusOK, response)
  29. }
  30. // StreamDetailStatus streams Nginx detailed status information using SSE
  31. func StreamDetailStatus(c *gin.Context) {
  32. // Set SSE response headers
  33. c.Header("Content-Type", "text/event-stream")
  34. c.Header("Cache-Control", "no-cache")
  35. c.Header("Connection", "keep-alive")
  36. c.Header("Access-Control-Allow-Origin", "*")
  37. // Create context that cancels when client disconnects
  38. ctx := c.Request.Context()
  39. // Create a ticker channel to prevent goroutine leaks
  40. ticker := time.NewTicker(5 * time.Second)
  41. defer ticker.Stop()
  42. // Send initial data immediately
  43. sendPerformanceData(c)
  44. // Use goroutine to send data periodically
  45. for {
  46. select {
  47. case <-ticker.C:
  48. // Send performance data
  49. if err := sendPerformanceData(c); err != nil {
  50. logger.Warn("Error sending SSE data:", err)
  51. return
  52. }
  53. case <-ctx.Done():
  54. // Client closed connection or request canceled
  55. logger.Debug("Client closed connection")
  56. return
  57. }
  58. }
  59. }
  60. // sendPerformanceData sends performance data once
  61. func sendPerformanceData(c *gin.Context) error {
  62. response := performance.GetPerformanceData()
  63. // Send SSE event
  64. c.SSEvent("message", response)
  65. // Flush buffer to ensure data is sent immediately
  66. c.Writer.Flush()
  67. return nil
  68. }
  69. // CheckStubStatus gets Nginx stub_status module status
  70. func CheckStubStatus(c *gin.Context) {
  71. stubStatus := performance.GetStubStatus()
  72. c.JSON(http.StatusOK, stubStatus)
  73. }
  74. // ToggleStubStatus enables or disables stub_status module
  75. func ToggleStubStatus(c *gin.Context) {
  76. var json struct {
  77. Enable bool `json:"enable"`
  78. }
  79. if !cosy.BindAndValid(c, &json) {
  80. return
  81. }
  82. stubStatus := performance.GetStubStatus()
  83. // If current status matches desired status, no action needed
  84. if stubStatus.Enabled == json.Enable {
  85. c.JSON(http.StatusOK, stubStatus)
  86. return
  87. }
  88. var err error
  89. if json.Enable {
  90. err = performance.EnableStubStatus()
  91. } else {
  92. err = performance.DisableStubStatus()
  93. }
  94. if err != nil {
  95. cosy.ErrHandler(c, err)
  96. return
  97. }
  98. // Reload Nginx configuration
  99. reloadOutput := nginx.Reload()
  100. if len(reloadOutput) > 0 && (strings.Contains(strings.ToLower(reloadOutput), "error") ||
  101. strings.Contains(strings.ToLower(reloadOutput), "failed")) {
  102. cosy.ErrHandler(c, errors.New("Reload Nginx failed"))
  103. return
  104. }
  105. // Check status after operation
  106. newStubStatus := performance.GetStubStatus()
  107. c.JSON(http.StatusOK, newStubStatus)
  108. }