Files
CMS/docs/monitoring-alerts-consolidated-report.md

733 lines
24 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📊 Monitoring & Alerts System - Consolidated Implementation Report
**Date**: 2025-11-30
**Status**: ✅ Skeleton Implemented (30% Complete)
**Build**: ✅ Success
---
## 📋 Executive Summary
اسکلت کامل سیستم Monitoring & Alerts پیاده‌سازی شد. این سیستم شامل دو بخش اصلی است:
1. **Alert System**: اعلان‌های مدیریتی (Critical/Warning/Success) برای Admin
2. **User Notification System**: اعلان‌های کاربری (SMS/Email/Push) برای Users
فعلاً فقط Logging فعال است. Integration های اصلی (Sentry, Slack, SMS) آماده پیاده‌سازی هستند.
---
## 🏗️ Architecture Overview
```
┌─────────────────────────────────────────────────────────┐
│ Application Layer │
│ ┌─────────────────────┐ ┌─────────────────────────┐ │
│ │ IAlertService │ │ IUserNotificationService│ │
│ │ - Critical │ │ - Commission Received │ │
│ │ - Warning │ │ - Club Activation │ │
│ │ - Success │ │ - Payout Error │ │
│ └─────────────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
↓ implements
┌─────────────────────────────────────────────────────────┐
│ Infrastructure Layer │
│ ┌─────────────────────┐ ┌─────────────────────────┐ │
│ │ AlertService │ │ UserNotificationService │ │
│ │ ✅ Logging │ │ ✅ Logging │ │
│ │ ⏳ Sentry │ │ ⏳ SMS Gateway │ │
│ │ ⏳ Slack │ │ ⏳ Email Service │ │
│ │ ⏳ Email │ │ ⏳ Push Notification │ │
│ └─────────────────────┘ └─────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ MonitoringSettings (Configuration) │ │
│ │ - SentryEnabled, SentryDsn │ │
│ │ - SlackEnabled, SlackWebhookUrl │ │
│ │ - EmailAlertsEnabled, AdminEmails │ │
│ │ - SmsNotificationsEnabled, SmsApiKey │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
↓ used by
┌─────────────────────────────────────────────────────────┐
│ Background Workers / Handlers │
│ ┌──────────────────────────────────────────────────┐ │
│ │ WeeklyNetworkCommissionWorker │ │
│ │ - On Success: SendSuccessNotificationAsync() │ │
│ │ - On Error: SendCriticalAlertAsync() │ │
│ └──────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ ProcessUserPayoutsCommandHandler │ │
│ │ - On Payout: SendCommissionReceivedNotification│ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
```
---
## 📦 Implementation Details
### 1⃣ Alert Service (Admin Notifications)
**Interface**: `CMSMicroservice.Application/Common/Interfaces/IAlertService.cs`
```csharp
public interface IAlertService
{
Task SendCriticalAlertAsync(string title, string message, Exception? exception, CancellationToken ct);
Task SendWarningAlertAsync(string title, string message, CancellationToken ct);
Task SendSuccessNotificationAsync(string title, string message, CancellationToken ct);
}
```
**Implementation**: `CMSMicroservice.Infrastructure/Services/Monitoring/AlertService.cs`
**Current Behavior**:
```
🚨 CRITICAL ALERT: {Title} - {Message}
⚠️ WARNING ALERT: {Title} - {Message}
✅ SUCCESS: {Title} - {Message}
```
**Pending Integrations**:
- **Sentry**: Exception tracking & aggregation (TODO: `SentrySdk.CaptureException()`)
- **Slack**: Real-time alerts to channel (TODO: HTTP POST to webhook)
- **Email**: Alert emails to admin list (TODO: SMTP integration)
---
### 2⃣ User Notification Service
**Interface**: `CMSMicroservice.Application/Common/Interfaces/IAlertService.cs` (same file)
```csharp
public interface IUserNotificationService
{
Task SendCommissionReceivedNotificationAsync(long userId, decimal amount, int weekNumber, CancellationToken ct);
Task SendClubActivationNotificationAsync(long userId, CancellationToken ct);
Task SendPayoutErrorNotificationAsync(long userId, string errorMessage, CancellationToken ct);
}
```
**Implementation**: `CMSMicroservice.Infrastructure/Services/Monitoring/UserNotificationService.cs`
**Current Behavior**:
```
📧 Sending commission notification: User={UserId}, Amount={Amount}, Week={WeekNumber}
🎉 Sending club activation notification: User={UserId}
⚠️ Sending payout error notification: User={UserId}, Error={Error}
```
**Pending Integrations**:
- **SMS Gateway**: Kavenegar/Ghasedak integration (TODO: HTTP API call)
- **Email Service**: SMTP/SendGrid integration (TODO: template-based emails)
- **Push Notification**: FCM/OneSignal integration (TODO: mobile app notifications)
---
### 3⃣ Configuration Model
**File**: `CMSMicroservice.Infrastructure/Services/Monitoring/MonitoringSettings.cs`
```csharp
public class MonitoringSettings
{
public const string SectionName = "Monitoring";
// Sentry
public bool SentryEnabled { get; set; }
public string? SentryDsn { get; set; }
// Slack
public bool SlackEnabled { get; set; }
public string? SlackWebhookUrl { get; set; }
// Email Alerts (Admin)
public bool EmailAlertsEnabled { get; set; }
public List<string> AdminEmails { get; set; }
// SMS (User Notifications)
public bool SmsNotificationsEnabled { get; set; }
public string? SmsApiKey { get; set; }
public string? SmsGatewayUrl { get; set; }
}
```
**Config File**: `CMSMicroservice.WebApi/appsettings.json`
```json
{
"Monitoring": {
"SentryEnabled": false,
"SentryDsn": "",
"SlackEnabled": false,
"SlackWebhookUrl": "",
"EmailAlertsEnabled": false,
"AdminEmails": ["admin@example.com"],
"SmsNotificationsEnabled": false,
"SmsApiKey": "",
"SmsGatewayUrl": ""
}
}
```
---
### 4⃣ Dependency Injection
**File**: `CMSMicroservice.Infrastructure/ConfigureServices.cs`
```csharp
services.AddScoped<IAlertService, AlertService>();
services.AddScoped<IUserNotificationService, UserNotificationService>();
```
---
### 5⃣ Worker Integration
**File**: `CMSMicroservice.Infrastructure/BackgroundJobs/WeeklyNetworkCommissionWorker.cs`
**On Success**:
```csharp
await alertService.SendSuccessNotificationAsync(
"Weekly Commission Completed",
$"Week {previousWeekNumber}: {payoutsProcessed} payouts, {balancesToExpire.Count} balances expired");
```
**On Error**:
```csharp
await alertService.SendCriticalAlertAsync(
"Weekly Commission Worker Failed",
$"Worker execution {executionId} failed for week {GetPreviousWeekNumber()}",
ex,
cancellationToken);
```
---
## 🔌 Integration Roadmap
### Priority 1: Sentry (High - 1 hour)
**Why**: Critical error tracking & aggregation برای Production
**Steps**:
1. Install NuGet:
```bash
dotnet add package Sentry.AspNetCore
```
2. Configure in `Program.cs`:
```csharp
builder.WebHost.UseSentry(options =>
{
options.Dsn = builder.Configuration["Monitoring:SentryDsn"];
options.Environment = builder.Environment.EnvironmentName;
options.TracesSampleRate = 1.0;
});
```
3. Update `AlertService.SendCriticalAlertAsync()`:
```csharp
if (_settings.SentryEnabled && exception != null)
{
SentrySdk.CaptureException(exception, scope =>
{
scope.SetTag("alert.title", title);
scope.SetExtra("message", message);
});
}
```
4. Set DSN in `appsettings.Production.json`:
```json
{
"Monitoring": {
"SentryEnabled": true,
"SentryDsn": "https://xxxxx@sentry.io/12345"
}
}
```
---
### Priority 2: Slack Webhook (Medium - 2 hours)
**Why**: Real-time alerts به تیم Development/DevOps
**Steps**:
1. Create Incoming Webhook در Slack:
- Go to: `https://api.slack.com/apps`
- Create app → Incoming Webhooks → Add to channel
- Copy Webhook URL
2. Update `AlertService`:
```csharp
private readonly HttpClient _httpClient;
public async Task SendCriticalAlertAsync(...)
{
_logger.LogCritical(exception, "🚨 {Title} - {Message}", title, message);
if (_settings.SlackEnabled)
{
var payload = new
{
text = $"🚨 *{title}*",
attachments = new[]
{
new
{
color = "danger",
text = message,
fields = exception != null ? new[]
{
new { title = "Exception", value = exception.Message, @short = false }
} : null
}
}
};
await _httpClient.PostAsJsonAsync(_settings.SlackWebhookUrl, payload);
}
}
```
3. Set Webhook URL in config:
```json
{
"Monitoring": {
"SlackEnabled": true,
"SlackWebhookUrl": "https://hooks.slack.com/services/T00/B00/XXX"
}
}
```
---
### Priority 3: SMS Gateway - Kavenegar (Medium - 3 hours)
**Why**: اطلاع‌رسانی کمیسیون به کاربران
**Steps**:
1. Get API Key from Kavenegar:
- Sign up: `https://panel.kavenegar.com`
- API Key: Settings → API Key
2. Create `ISmsGatewayService`:
```csharp
public interface ISmsGatewayService
{
Task SendAsync(string mobile, string message, CancellationToken ct = default);
}
```
3. Implement `KavenegarSmsService`:
```csharp
public class KavenegarSmsService : ISmsGatewayService
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
public async Task SendAsync(string mobile, string message, CancellationToken ct)
{
var url = $"https://api.kavenegar.com/v1/{_apiKey}/sms/send.json";
var payload = new
{
receptor = mobile,
message = message
};
var response = await _httpClient.PostAsJsonAsync(url, payload, ct);
response.EnsureSuccessStatusCode();
}
}
```
4. Update `UserNotificationService.SendCommissionReceivedNotificationAsync()`:
```csharp
var user = await _context.Users.FindAsync(userId, ct);
if (user.SmsNotifications && _settings.SmsNotificationsEnabled)
{
var message = $"کمیسیون شما: {amount:N0} ریال برای هفته {weekNumber} واریز شد.";
await _smsGateway.SendAsync(user.Mobile, message, ct);
}
```
5. Configure:
```json
{
"Monitoring": {
"SmsNotificationsEnabled": true,
"SmsApiKey": "your-kavenegar-api-key"
}
}
```
---
### Priority 4: Email Alerts for Admins (Low - 2 hours)
**Why**: Backup notification channel
**Options**:
- **A) MailKit (SMTP)**:
```csharp
using var client = new SmtpClient();
await client.ConnectAsync("smtp.gmail.com", 587, SecureSocketOptions.StartTls);
await client.AuthenticateAsync("user@example.com", "password");
var message = new MimeMessage();
message.From.Add(new MailboxAddress("CMS Alerts", "noreply@foursat.ir"));
message.To.Add(new MailboxAddress("Admin", adminEmail));
message.Subject = $"[ALERT] {title}";
message.Body = new TextPart("html") { Text = htmlMessage };
await client.SendAsync(message);
```
- **B) SendGrid API**:
```csharp
var client = new SendGridClient(_settings.SendGridApiKey);
var msg = MailHelper.CreateSingleEmail(
from: new EmailAddress("noreply@foursat.ir", "CMS Alerts"),
to: new EmailAddress(adminEmail),
subject: $"[ALERT] {title}",
plainTextContent: message,
htmlContent: htmlMessage
);
await client.SendEmailAsync(msg);
```
**Config**:
```json
{
"Monitoring": {
"EmailAlertsEnabled": true,
"AdminEmails": ["admin@foursat.ir", "devops@foursat.ir"],
"SmtpServer": "smtp.gmail.com",
"SmtpPort": 587,
"SmtpUsername": "user@example.com",
"SmtpPassword": "password"
}
}
```
---
### Priority 5: Retry Logic با Exponential Backoff (Low - 1 hour)
**Why**: بهبود Reliability در صورت خطاهای Transient
**Implementation در Worker**:
```csharp
private async Task<T> RetryWithExponentialBackoffAsync<T>(
Func<Task<T>> operation,
int maxRetries = 3,
CancellationToken ct = default)
{
for (int attempt = 0; attempt <= maxRetries; attempt++)
{
try
{
return await operation();
}
catch (Exception ex) when (attempt < maxRetries && IsTransientError(ex))
{
var delay = TimeSpan.FromSeconds(Math.Pow(2, attempt)); // 2^n: 1s, 2s, 4s
_logger.LogWarning(ex,
"Attempt {Attempt}/{MaxRetries} failed. Retrying in {Delay}s...",
attempt + 1, maxRetries, delay.TotalSeconds);
await Task.Delay(delay, ct);
}
}
throw new InvalidOperationException($"Operation failed after {maxRetries} retries");
}
private bool IsTransientError(Exception ex)
{
return ex is TimeoutException
|| ex is HttpRequestException
|| (ex is SqlException sqlEx && sqlEx.IsTransient);
}
```
**Usage**:
```csharp
// در ExecuteWeeklyCalculationAsync():
var balancesCalculated = await RetryWithExponentialBackoffAsync(async () =>
{
return await mediator.Send(new CalculateWeeklyBalancesCommand
{
WeekNumber = previousWeekNumber
}, cancellationToken);
}, maxRetries: 3, ct: cancellationToken);
```
---
## 🧪 Testing Guide
### Test 1: Alert Service (Console Logging)
```csharp
// در Controller یا Handler:
var alertService = _serviceProvider.GetRequiredService<IAlertService>();
await alertService.SendCriticalAlertAsync(
"Test Critical Alert",
"این یک تست برای Alert Service است",
new Exception("Sample exception"));
await alertService.SendSuccessNotificationAsync(
"Test Success",
"عملیات با موفقیت انجام شد");
```
**Expected Output**:
```
🚨 CRITICAL ALERT: Test Critical Alert - این یک تست برای Alert Service است
✅ SUCCESS: Test Success - عملیات با موفقیت انجام شد
```
---
### Test 2: User Notification Service
```csharp
var notificationService = _serviceProvider.GetRequiredService<IUserNotificationService>();
await notificationService.SendCommissionReceivedNotificationAsync(
userId: 123,
amount: 500_000,
weekNumber: 48);
```
**Expected Output**:
```
📧 Sending commission notification: User=123, Amount=500000, Week=48
```
---
### Test 3: Worker Integration
```bash
# Run Worker manually (for testing)
# تغییر زمان اجرا به 1 دقیقه بعد برای تست:
# در Worker: var delay = TimeSpan.FromMinutes(1);
dotnet run --project CMSMicroservice.WebApi
```
**Expected**:
- Worker starts
- After 1 minute → Executes calculation
- On success → Logs: `✅ SUCCESS: Weekly Commission Completed`
- On error → Logs: `🚨 CRITICAL ALERT: Weekly Commission Worker Failed`
---
### Test 4: Sentry Integration (بعد از پیاده‌سازی)
```csharp
// Throw یک exception برای تست:
throw new InvalidOperationException("Test Sentry integration");
```
**Check**: Sentry dashboard → Issues → باید exception جدید نمایش داده شود
---
### Test 5: Slack Integration (بعد از پیاده‌سازی)
```csharp
await alertService.SendCriticalAlertAsync("Test Slack", "Testing webhook integration", null);
```
**Check**: Slack channel → باید پیام جدید نمایش داده شود
---
### Test 6: SMS Integration (بعد از پیاده‌سازی)
```csharp
await notificationService.SendCommissionReceivedNotificationAsync(
userId: YOUR_USER_ID, // با شماره موبایل معتبر
amount: 100_000,
weekNumber: 48);
```
**Check**: موبایل کاربر → باید SMS دریافت شود
---
## 📊 Current Status & Progress
| Component | Status | Completion | Notes |
|-----------|--------|------------|-------|
| **Interfaces** | ✅ Done | 100% | `IAlertService`, `IUserNotificationService` |
| **Skeleton Implementations** | ✅ Done | 100% | Logging only |
| **Configuration Model** | ✅ Done | 100% | `MonitoringSettings` |
| **DI Registration** | ✅ Done | 100% | In `ConfigureServices.cs` |
| **Worker Integration** | ✅ Done | 100% | Success + Error alerts |
| **appsettings Structure** | ✅ Done | 100% | Monitoring section added |
| **Sentry Integration** | ⏳ Pending | 0% | Install package + configure DSN |
| **Slack Webhook** | ⏳ Pending | 0% | Create webhook + implement POST |
| **SMS Gateway** | ⏳ Pending | 0% | Choose provider + get API key |
| **Email Alerts** | ⏳ Pending | 0% | SMTP/SendGrid integration |
| **Retry Logic** | ⏳ Pending | 0% | Exponential backoff implementation |
| **Testing** | ⏳ Pending | 0% | Unit + Integration tests |
**Overall Progress**: 30% ✅ | 70% ⏳
---
## 📝 Important Notes
### 1. Production Readiness
- ⚠️ **فعلاً فقط Logging فعال است**
- ⚠️ برای Production **حداقل Sentry** باید فعال شود
- ⚠️ برای Critical systems حتماً Slack هم اضافه شود
### 2. User Preferences
- SMS/Email/Push باید بر اساس تنظیمات کاربر (`User.SmsNotifications`, etc.) ارسال شود
- در `UserNotificationService` باید ابتدا preferences چک شود
### 3. Rate Limiting
- برای SMS Gateway باید Rate Limiting در نظر گرفته شود
- پیشنهاد: استفاده از Queue (Hangfire/RabbitMQ) برای ارسال تعداد زیاد SMS
### 4. Cost Management
- SMS و Email هزینه دارند
- پیشنهاد: Batching برای ارسال گروهی
- پیشنهاد: Template-based messaging برای کاهش هزینه
### 5. Security
- API Keys در `appsettings.json` نباید commit شوند
- استفاده از Environment Variables یا Azure Key Vault
- مثال: `SmsApiKey: ${SMS_API_KEY}` در appsettings
### 6. Monitoring the Monitor
- خود Alert System هم باید Monitor شود
- اگر Slack/SMS fail شد، باید Fallback به Email یا Log باشد
- پیشنهاد: Dead Letter Queue برای failed notifications
---
## 🔗 File Reference Map
```
CMS/
├── src/
│ ├── CMSMicroservice.Application/
│ │ └── Common/
│ │ └── Interfaces/
│ │ └── IAlertService.cs ⭐
│ │
│ ├── CMSMicroservice.Infrastructure/
│ │ ├── Services/
│ │ │ └── Monitoring/
│ │ │ ├── AlertService.cs ⭐
│ │ │ ├── UserNotificationService.cs ⭐
│ │ │ └── MonitoringSettings.cs ⭐
│ │ │
│ │ ├── BackgroundJobs/
│ │ │ └── WeeklyNetworkCommissionWorker.cs ✏️ (Modified)
│ │ │
│ │ └── ConfigureServices.cs ✏️ (Modified)
│ │
│ └── CMSMicroservice.WebApi/
│ └── appsettings.json ✏️ (Modified)
└── docs/
└── monitoring-alerts-implementation-report.md 📄 (This file)
```
**Legend**:
- ⭐ = New file created
- ✏️ = Existing file modified
- 📄 = Documentation
---
## 🚀 Next Action Items
### Immediate (این هفته):
1. ✅ Review this document
2. ⏳ Decision: کدام Integration اول؟ (پیشنهاد: Sentry)
3. ⏳ Get credentials:
- Sentry DSN
- Slack Webhook URL
- SMS Gateway API Key
### Short-term (هفته آینده):
4. ⏳ Implement Sentry integration
5. ⏳ Implement Slack webhook
6. ⏳ Test in Staging environment
### Long-term (ماه آینده):
7. ⏳ Implement SMS Gateway (Kavenegar)
8. ⏳ Add Email alerts
9. ⏳ Implement Retry logic
10. ⏳ Write Unit/Integration tests
11. ⏳ Deploy to Production
---
## 📞 Contact & Support
**Implementation Questions**:
- Developer: GitHub Copilot (این گزارش)
- Review: Development Team
**Service Providers**:
- **Sentry**: https://sentry.io (Error tracking)
- **Slack**: https://api.slack.com/messaging/webhooks (Webhooks)
- **Kavenegar**: https://kavenegar.com (SMS Gateway - Iran)
- **Ghasedak**: https://ghasedak.me (SMS Gateway Alternative)
- **SendGrid**: https://sendgrid.com (Email service)
---
**Last Updated**: 2025-11-30
**Build Status**: ✅ Success
**Ready for**: Integration implementation
---
## 🎯 TL;DR (خلاصه برای رجوع سریع)
### چی ساخته شد:
- ✅ `IAlertService` + `AlertService` (Admin alerts)
- ✅ `IUserNotificationService` + `UserNotificationService` (User notifications)
- ✅ `MonitoringSettings` (Configuration model)
- ✅ Worker integration (Success/Error alerts)
- ✅ DI registration
- ✅ appsettings structure
### فعلاً چی کار می‌کنه:
- Logging به Console (🚨 Critical, ⚠️ Warning, ✅ Success)
### چی باید اضافه بشه:
1. **Sentry** - Error tracking (Priority: High)
2. **Slack** - Real-time alerts (Priority: Medium)
3. **SMS Gateway** - User notifications (Priority: Medium)
4. **Email** - Backup channel (Priority: Low)
5. **Retry Logic** - Reliability (Priority: Low)
### کجا باید نگاه کنی:
- Interfaces: `CMSMicroservice.Application/Common/Interfaces/IAlertService.cs`
- Implementations: `CMSMicroservice.Infrastructure/Services/Monitoring/`
- Worker: `CMSMicroservice.Infrastructure/BackgroundJobs/WeeklyNetworkCommissionWorker.cs`
- Config: `CMSMicroservice.WebApi/appsettings.json`
### چطوری تست کنی:
```csharp
await alertService.SendCriticalAlertAsync("Test", "Message", null);
// Output: 🚨 CRITICAL ALERT: Test - Message
```
### بعدش چیکار کنم:
1. Get Sentry DSN → Update appsettings.Production.json
2. Install `Sentry.AspNetCore` → Configure in Program.cs
3. Update `AlertService.SendCriticalAlertAsync()` → Add `SentrySdk.CaptureException()`
4. Test → Deploy