Index.cshtml 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. @page
  2. @model IndexModel
  3. @using SharedKernel.Extensions
  4. @{
  5. ViewData["Title"] = "상황판";
  6. var h = Model.MailHealth;
  7. // 상태 단계 결정 (가장 심각한 시그널 기준)
  8. string mailLevel = "ok";
  9. string mailMessage = "정상";
  10. if (h.ProcessingStuckCount > 0)
  11. {
  12. mailLevel = "danger";
  13. mailMessage = $"Processing 갇힘 {h.ProcessingStuckCount}건 — 워커 다운/락 의심";
  14. }
  15. else if (h.StalePendingCount > 0)
  16. {
  17. mailLevel = "danger";
  18. mailMessage = $"24시간 이상 미처리 Pending {h.StalePendingCount}건 — Janitor 또는 SMTP 점검";
  19. }
  20. else if (h.PendingCount >= 1000)
  21. {
  22. mailLevel = "danger";
  23. mailMessage = $"큐 적체 {h.PendingCount:N0}건 — 큰 폭 처리 지연";
  24. }
  25. else if (h.PendingCount >= 100)
  26. {
  27. mailLevel = "warning";
  28. mailMessage = $"큐 적체 {h.PendingCount:N0}건 — 처리 지연 주의";
  29. }
  30. else if (h.OldestPendingAt.HasValue && (DateTime.UtcNow - h.OldestPendingAt.Value).TotalHours >= 1)
  31. {
  32. mailLevel = "warning";
  33. mailMessage = $"가장 오래된 Pending이 1시간 이상 — 폴링 점검";
  34. }
  35. string mailBadgeClass = mailLevel switch
  36. {
  37. "danger" => "bg-danger",
  38. "warning" => "bg-warning text-dark",
  39. _ => "bg-success"
  40. };
  41. string mailBadgeLabel = mailLevel switch
  42. {
  43. "danger" => "위험",
  44. "warning" => "주의",
  45. _ => "정상"
  46. };
  47. string oldestPendingDisplay = h.OldestPendingAt.HasValue
  48. ? $"{h.OldestPendingAt.Value.GetDateAt()} ({(int)(DateTime.UtcNow - h.OldestPendingAt.Value).TotalMinutes}분 전)"
  49. : "-";
  50. }
  51. <div class="container-fluid">
  52. <h3>@ViewData["Title"]</h3>
  53. <hr />
  54. <div class="row g-3">
  55. <div class="col-12 col-xl-6">
  56. <div class="card">
  57. <div class="card-header d-flex justify-content-between align-items-center">
  58. <strong>Mail Queue 상태</strong>
  59. <span class="badge @mailBadgeClass">@mailBadgeLabel</span>
  60. </div>
  61. <div class="card-body">
  62. <p class="text-muted small mb-3">@mailMessage</p>
  63. <div class="row row-cols-2 row-cols-md-3 g-2 mb-3">
  64. <div class="col">
  65. <div class="border rounded p-2 text-center">
  66. <div class="text-muted small">대기</div>
  67. <div class="fs-5 fw-bold @(h.PendingCount >= 1000 ? "text-danger" : h.PendingCount >= 100 ? "text-warning" : null)">@h.PendingCount.ToString("N0")</div>
  68. </div>
  69. </div>
  70. <div class="col">
  71. <div class="border rounded p-2 text-center">
  72. <div class="text-muted small">처리 중 (5분 +)</div>
  73. <div class="fs-5 fw-bold @(h.ProcessingStuckCount > 0 ? "text-danger" : null)">@h.ProcessingStuckCount.ToString("N0")</div>
  74. </div>
  75. </div>
  76. <div class="col">
  77. <div class="border rounded p-2 text-center">
  78. <div class="text-muted small">stale (24h +)</div>
  79. <div class="fs-5 fw-bold @(h.StalePendingCount > 0 ? "text-danger" : null)">@h.StalePendingCount.ToString("N0")</div>
  80. </div>
  81. </div>
  82. <div class="col">
  83. <div class="border rounded p-2 text-center">
  84. <div class="text-muted small">최근 24h 발송</div>
  85. <div class="fs-5 fw-bold text-success">@h.Sent24hCount.ToString("N0")</div>
  86. </div>
  87. </div>
  88. <div class="col">
  89. <div class="border rounded p-2 text-center">
  90. <div class="text-muted small">최근 24h 실패</div>
  91. <div class="fs-5 fw-bold @(h.Failed24hCount > 0 ? "text-warning" : null)">@h.Failed24hCount.ToString("N0")</div>
  92. </div>
  93. </div>
  94. <div class="col">
  95. <div class="border rounded p-2 text-center">
  96. <div class="text-muted small">전체 행 수</div>
  97. <div class="fs-5 fw-bold">@h.TotalRowCount.ToString("N0")</div>
  98. </div>
  99. </div>
  100. </div>
  101. <table class="table table-sm mb-3">
  102. <tbody>
  103. <tr>
  104. <th class="w-25 text-muted fw-normal">가장 오래된 Pending</th>
  105. <td>@oldestPendingDisplay</td>
  106. </tr>
  107. </tbody>
  108. </table>
  109. </div>
  110. </div>
  111. </div>
  112. </div>
  113. </div>