log_writer.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package xray
  2. import (
  3. "regexp"
  4. "runtime"
  5. "strings"
  6. "x-ui/logger"
  7. )
  8. func NewLogWriter() *LogWriter {
  9. return &LogWriter{}
  10. }
  11. type LogWriter struct {
  12. lastLine string
  13. }
  14. func (lw *LogWriter) Write(m []byte) (n int, err error) {
  15. crashRegex := regexp.MustCompile(`(?i)(panic|exception|stack trace|fatal error)`)
  16. // Convert the data to a string
  17. message := strings.TrimSpace(string(m))
  18. msgLowerAll := strings.ToLower(message)
  19. // Suppress noisy Windows process-kill signal that surfaces as exit status 1
  20. if runtime.GOOS == "windows" && strings.Contains(msgLowerAll, "exit status 1") {
  21. return len(m), nil
  22. }
  23. // Check if the message contains a crash
  24. if crashRegex.MatchString(message) {
  25. logger.Debug("Core crash detected:\n", message)
  26. lw.lastLine = message
  27. err1 := writeCrashReport(m)
  28. if err1 != nil {
  29. logger.Error("Unable to write crash report:", err1)
  30. }
  31. return len(m), nil
  32. }
  33. regex := regexp.MustCompile(`^(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}\.\d{6}) \[([^\]]+)\] (.+)$`)
  34. messages := strings.SplitSeq(message, "\n")
  35. for msg := range messages {
  36. matches := regex.FindStringSubmatch(msg)
  37. if len(matches) > 3 {
  38. level := matches[2]
  39. msgBody := matches[3]
  40. msgBodyLower := strings.ToLower(msgBody)
  41. if strings.Contains(msgBodyLower, "tls handshake error") ||
  42. strings.Contains(msgBodyLower, "connection ends") {
  43. logger.Debug("XRAY: " + msgBody)
  44. lw.lastLine = ""
  45. continue
  46. }
  47. if strings.Contains(msgBodyLower, "failed") {
  48. logger.Error("XRAY: " + msgBody)
  49. } else {
  50. switch level {
  51. case "Debug":
  52. logger.Debug("XRAY: " + msgBody)
  53. case "Info":
  54. logger.Info("XRAY: " + msgBody)
  55. case "Warning":
  56. logger.Warning("XRAY: " + msgBody)
  57. case "Error":
  58. logger.Error("XRAY: " + msgBody)
  59. default:
  60. logger.Debug("XRAY: " + msg)
  61. }
  62. }
  63. lw.lastLine = ""
  64. } else if msg != "" {
  65. msgLower := strings.ToLower(msg)
  66. if strings.Contains(msgLower, "tls handshake error") ||
  67. strings.Contains(msgLower, "connection ends") {
  68. logger.Debug("XRAY: " + msg)
  69. lw.lastLine = msg
  70. continue
  71. }
  72. if strings.Contains(msgLower, "failed") {
  73. logger.Error("XRAY: " + msg)
  74. } else {
  75. logger.Debug("XRAY: " + msg)
  76. }
  77. lw.lastLine = msg
  78. }
  79. }
  80. return len(m), nil
  81. }