| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- <?php
- namespace App\Module\ThirdParty\Events;
- use App\Module\ThirdParty\Models\ThirdPartyService;
- use App\Module\ThirdParty\Models\ThirdPartyQuota;
- use App\Module\ThirdParty\Enums\QUOTA_TYPE;
- use Illuminate\Foundation\Events\Dispatchable;
- use Illuminate\Queue\SerializesModels;
- /**
- * 配额告警事件
- *
- * 当第三方服务配额达到告警阈值时触发此事件
- */
- class QuotaAlertEvent
- {
- use Dispatchable, SerializesModels;
- /**
- * 第三方服务实例
- *
- * @var ThirdPartyService
- */
- public ThirdPartyService $service;
- /**
- * 配额实例
- *
- * @var ThirdPartyQuota
- */
- public ThirdPartyQuota $quota;
- /**
- * 告警类型
- *
- * @var string
- */
- public string $alertType;
- /**
- * 当前使用量
- *
- * @var int
- */
- public int $currentUsage;
- /**
- * 配额限制
- *
- * @var int
- */
- public int $quotaLimit;
- /**
- * 使用百分比
- *
- * @var float
- */
- public float $usagePercentage;
- /**
- * 告警阈值
- *
- * @var float
- */
- public float $alertThreshold;
- /**
- * 告警时间
- *
- * @var \Carbon\Carbon
- */
- public \Carbon\Carbon $alertTime;
- /**
- * 额外数据
- *
- * @var array
- */
- public array $metadata;
- // 告警类型常量
- public const ALERT_TYPE_WARNING = 'warning'; // 警告:达到警告阈值
- public const ALERT_TYPE_CRITICAL = 'critical'; // 严重:达到严重阈值
- public const ALERT_TYPE_EXHAUSTED = 'exhausted'; // 耗尽:配额用完
- /**
- * 创建事件实例
- *
- * @param ThirdPartyService $service
- * @param ThirdPartyQuota $quota
- * @param string $alertType
- * @param int $currentUsage
- * @param int $quotaLimit
- * @param float $usagePercentage
- * @param float $alertThreshold
- * @param array $metadata
- */
- public function __construct(
- ThirdPartyService $service,
- ThirdPartyQuota $quota,
- string $alertType,
- int $currentUsage,
- int $quotaLimit,
- float $usagePercentage,
- float $alertThreshold,
- array $metadata = []
- ) {
- $this->service = $service;
- $this->quota = $quota;
- $this->alertType = $alertType;
- $this->currentUsage = $currentUsage;
- $this->quotaLimit = $quotaLimit;
- $this->usagePercentage = $usagePercentage;
- $this->alertThreshold = $alertThreshold;
- $this->alertTime = now();
- $this->metadata = $metadata;
- }
- /**
- * 获取事件数据数组
- *
- * @return array
- */
- public function toArray(): array
- {
- return [
- 'service_id' => $this->service->id,
- 'service_code' => $this->service->code,
- 'service_name' => $this->service->name,
- 'quota_id' => $this->quota->id,
- 'quota_type' => $this->quota->quota_type,
- 'quota_type_label' => QUOTA_TYPE::from($this->quota->quota_type)->getLabel(),
- 'alert_type' => $this->alertType,
- 'current_usage' => $this->currentUsage,
- 'quota_limit' => $this->quotaLimit,
- 'usage_percentage' => $this->usagePercentage,
- 'alert_threshold' => $this->alertThreshold,
- 'alert_time' => $this->alertTime->toISOString(),
- 'metadata' => $this->metadata,
- ];
- }
- /**
- * 获取告警级别
- *
- * @return string
- */
- public function getAlertLevel(): string
- {
- return match ($this->alertType) {
- self::ALERT_TYPE_WARNING => 'WARNING',
- self::ALERT_TYPE_CRITICAL => 'CRITICAL',
- self::ALERT_TYPE_EXHAUSTED => 'CRITICAL',
- default => 'INFO',
- };
- }
- /**
- * 获取告警消息
- *
- * @return string
- */
- public function getAlertMessage(): string
- {
- $serviceName = $this->service->name;
- $quotaTypeLabel = QUOTA_TYPE::from($this->quota->quota_type)->getLabel();
- $percentage = number_format($this->usagePercentage, 1);
- return match ($this->alertType) {
- self::ALERT_TYPE_WARNING => "第三方服务 [{$serviceName}] 的 {$quotaTypeLabel} 配额使用率已达到 {$percentage}%,请注意监控",
- self::ALERT_TYPE_CRITICAL => "第三方服务 [{$serviceName}] 的 {$quotaTypeLabel} 配额使用率已达到 {$percentage}%,即将耗尽",
- self::ALERT_TYPE_EXHAUSTED => "第三方服务 [{$serviceName}] 的 {$quotaTypeLabel} 配额已耗尽,服务调用将被限制",
- default => "第三方服务 [{$serviceName}] 配额状态更新",
- };
- }
- /**
- * 获取剩余配额
- *
- * @return int
- */
- public function getRemainingQuota(): int
- {
- return max(0, $this->quotaLimit - $this->currentUsage);
- }
- /**
- * 判断是否为严重告警
- *
- * @return bool
- */
- public function isCritical(): bool
- {
- return in_array($this->alertType, [self::ALERT_TYPE_CRITICAL, self::ALERT_TYPE_EXHAUSTED]);
- }
- /**
- * 获取预计耗尽时间
- *
- * @return \Carbon\Carbon|null
- */
- public function getEstimatedExhaustionTime(): ?\Carbon\Carbon
- {
- if ($this->alertType === self::ALERT_TYPE_EXHAUSTED) {
- return null; // 已经耗尽
- }
- // 基于当前使用率估算耗尽时间
- $quotaType = QUOTA_TYPE::from($this->quota->quota_type);
- $windowStart = \Carbon\Carbon::instance($quotaType->getCurrentWindowStart());
- $windowEnd = \Carbon\Carbon::instance($quotaType->getCurrentWindowEnd());
- $elapsedTime = now()->diffInMinutes($windowStart);
-
- if ($elapsedTime <= 0 || $this->currentUsage <= 0) {
- return null;
- }
- $usageRate = $this->currentUsage / $elapsedTime; // 每分钟使用量
- $remainingQuota = $this->getRemainingQuota();
-
- if ($usageRate <= 0) {
- return null;
- }
- $minutesToExhaustion = $remainingQuota / $usageRate;
-
- return now()->addMinutes($minutesToExhaustion);
- }
- /**
- * 获取建议操作
- *
- * @return array
- */
- public function getSuggestedActions(): array
- {
- $actions = [];
- switch ($this->alertType) {
- case self::ALERT_TYPE_WARNING:
- $actions[] = '监控配额使用情况';
- $actions[] = '检查是否有异常调用';
- $actions[] = '考虑优化调用频率';
- break;
- case self::ALERT_TYPE_CRITICAL:
- $actions[] = '立即检查调用情况';
- $actions[] = '暂停非必要的API调用';
- $actions[] = '联系服务提供商增加配额';
- $actions[] = '启用备用服务(如有)';
- break;
- case self::ALERT_TYPE_EXHAUSTED:
- $actions[] = '停止所有API调用';
- $actions[] = '等待配额重置';
- $actions[] = '切换到备用服务';
- $actions[] = '联系服务提供商紧急增加配额';
- break;
- }
- return $actions;
- }
- }
|