backendClientLogs.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { loadBackendBaseUrl } from './backendAuth'
  2. import { postClientLog, type BackendClientLogInput } from './backendApi'
  3. type ClientLogLevel = BackendClientLogInput['level']
  4. type ClientLogEntry = {
  5. level: ClientLogLevel
  6. category: string
  7. message: string
  8. eventId?: string
  9. releaseId?: string
  10. sessionId?: string
  11. manifestUrl?: string
  12. route?: string
  13. details?: Record<string, unknown>
  14. }
  15. const CLIENT_LOG_SOURCE = 'wechat-mini'
  16. const MAX_PENDING_CLIENT_LOGS = 100
  17. const pendingClientLogs: BackendClientLogInput[] = []
  18. let clientLogFlushInProgress = false
  19. let clientLogSequence = 0
  20. function getCurrentRoute(): string {
  21. const pages = getCurrentPages()
  22. if (!pages.length) {
  23. return ''
  24. }
  25. const current = pages[pages.length - 1]
  26. return current && current.route ? current.route : ''
  27. }
  28. function enqueueClientLog(payload: BackendClientLogInput) {
  29. pendingClientLogs.push(payload)
  30. if (pendingClientLogs.length > MAX_PENDING_CLIENT_LOGS) {
  31. pendingClientLogs.shift()
  32. }
  33. }
  34. function flushNextClientLog() {
  35. if (clientLogFlushInProgress || !pendingClientLogs.length) {
  36. return
  37. }
  38. const baseUrl = loadBackendBaseUrl()
  39. if (!baseUrl) {
  40. pendingClientLogs.length = 0
  41. return
  42. }
  43. const payload = pendingClientLogs.shift()
  44. if (!payload) {
  45. return
  46. }
  47. clientLogFlushInProgress = true
  48. postClientLog({
  49. baseUrl,
  50. payload,
  51. }).catch(() => {
  52. // 联调日志不打断主流程,失败时静默丢弃。
  53. }).finally(() => {
  54. clientLogFlushInProgress = false
  55. if (pendingClientLogs.length) {
  56. flushNextClientLog()
  57. }
  58. })
  59. }
  60. export function reportBackendClientLog(entry: ClientLogEntry) {
  61. clientLogSequence += 1
  62. const details = entry.details ? { ...entry.details } : {}
  63. details.seq = clientLogSequence
  64. const payload: BackendClientLogInput = {
  65. source: CLIENT_LOG_SOURCE,
  66. level: entry.level,
  67. category: entry.category,
  68. message: entry.message,
  69. eventId: entry.eventId || '',
  70. releaseId: entry.releaseId || '',
  71. sessionId: entry.sessionId || '',
  72. manifestUrl: entry.manifestUrl || '',
  73. route: entry.route || getCurrentRoute(),
  74. occurredAt: new Date().toISOString(),
  75. details,
  76. }
  77. enqueueClientLog(payload)
  78. flushNextClientLog()
  79. }