# 📊 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
