status.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. "net/http"
  7. "strings"
  8. "time"
  9. "github.com/0xJacky/Nginx-UI/api"
  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. api.SetSSEHeaders(c)
  34. // Create context that cancels when client disconnects
  35. ctx := c.Request.Context()
  36. // Create a ticker channel to prevent goroutine leaks
  37. ticker := time.NewTicker(5 * time.Second)
  38. defer ticker.Stop()
  39. // Send initial data immediately
  40. sendPerformanceData(c)
  41. // Use goroutine to send data periodically
  42. for {
  43. select {
  44. case <-ticker.C:
  45. // Send performance data
  46. if err := sendPerformanceData(c); err != nil {
  47. logger.Warn("Error sending SSE data:", err)
  48. return
  49. }
  50. case <-ctx.Done():
  51. // Client closed connection or request canceled
  52. logger.Debug("Client closed connection")
  53. return
  54. }
  55. }
  56. }
  57. // sendPerformanceData sends performance data once
  58. func sendPerformanceData(c *gin.Context) error {
  59. response := performance.GetPerformanceData()
  60. // Send SSE event
  61. c.SSEvent("message", response)
  62. // Flush buffer to ensure data is sent immediately
  63. c.Writer.Flush()
  64. return nil
  65. }
  66. // CheckStubStatus gets Nginx stub_status module status
  67. func CheckStubStatus(c *gin.Context) {
  68. stubStatus := performance.GetStubStatus()
  69. c.JSON(http.StatusOK, stubStatus)
  70. }
  71. // ToggleStubStatus enables or disables stub_status module
  72. func ToggleStubStatus(c *gin.Context) {
  73. var json struct {
  74. Enable bool `json:"enable"`
  75. }
  76. if !cosy.BindAndValid(c, &json) {
  77. return
  78. }
  79. stubStatus := performance.GetStubStatus()
  80. // If current status matches desired status, no action needed
  81. if stubStatus.Enabled == json.Enable {
  82. c.JSON(http.StatusOK, stubStatus)
  83. return
  84. }
  85. var err error
  86. if json.Enable {
  87. err = performance.EnableStubStatus()
  88. } else {
  89. err = performance.DisableStubStatus()
  90. }
  91. if err != nil {
  92. cosy.ErrHandler(c, err)
  93. return
  94. }
  95. // Reload Nginx configuration
  96. reloadOutput, err := nginx.Reload()
  97. if err != nil {
  98. cosy.ErrHandler(c, err)
  99. return
  100. }
  101. if len(reloadOutput) > 0 && (strings.Contains(strings.ToLower(reloadOutput), "error") ||
  102. strings.Contains(strings.ToLower(reloadOutput), "failed")) {
  103. cosy.ErrHandler(c, cosy.WrapErrorWithParams(nginx.ErrReloadFailed, reloadOutput))
  104. return
  105. }
  106. // Check status after operation
  107. newStubStatus := performance.GetStubStatus()
  108. c.JSON(http.StatusOK, newStubStatus)
  109. }