| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- <?php
- namespace App\Module\OpenAPI\Models;
- use UCore\ModelCore;
- /**
- * OpenAPI统计数据模型
- *
- * field start
- * field end
- */
- class OpenApiStats extends ModelCore
- {
- /**
- * 数据类型转换
- *
- * @var array
- */
- protected $casts = [
- 'date' => 'date',
- 'hour' => 'integer',
- 'request_count' => 'integer',
- 'success_count' => 'integer',
- 'error_count' => 'integer',
- 'avg_response_time' => 'float',
- 'max_response_time' => 'float',
- 'min_response_time' => 'float',
- 'rate_limit_hits' => 'integer',
- 'unique_ips' => 'integer',
- 'error_details' => 'array',
- ];
- /**
- * 默认值
- *
- * @var array
- */
- protected $attributes = [
- 'request_count' => 0,
- 'success_count' => 0,
- 'error_count' => 0,
- 'avg_response_time' => 0,
- 'max_response_time' => 0,
- 'min_response_time' => 0,
- 'rate_limit_hits' => 0,
- 'unique_ips' => 0,
- ];
- /**
- * 关联应用模型
- *
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function app()
- {
- return $this->belongsTo(OpenApiApp::class, 'app_id', 'app_id');
- }
- /**
- * 获取成功率
- *
- * @return float
- */
- public function getSuccessRateAttribute(): float
- {
- if ($this->request_count === 0) {
- return 0;
- }
- return round(($this->success_count / $this->request_count) * 100, 2);
- }
- /**
- * 获取错误率
- *
- * @return float
- */
- public function getErrorRateAttribute(): float
- {
- if ($this->request_count === 0) {
- return 0;
- }
- return round(($this->error_count / $this->request_count) * 100, 2);
- }
- /**
- * 获取限流命中率
- *
- * @return float
- */
- public function getRateLimitHitRateAttribute(): float
- {
- if ($this->request_count === 0) {
- return 0;
- }
- return round(($this->rate_limit_hits / $this->request_count) * 100, 2);
- }
- /**
- * 获取时间段标识
- *
- * @return string
- */
- public function getTimePeriodAttribute(): string
- {
- if ($this->hour !== null) {
- return $this->date->format('Y-m-d') . ' ' . sprintf('%02d:00', $this->hour);
- }
- return $this->date->format('Y-m-d');
- }
- /**
- * 获取格式化的平均响应时间
- *
- * @return string
- */
- public function getFormattedAvgResponseTimeAttribute(): string
- {
- if ($this->avg_response_time < 1000) {
- return round($this->avg_response_time, 2) . 'ms';
- }
- return round($this->avg_response_time / 1000, 2) . 's';
- }
- /**
- * 更新统计数据
- *
- * @param array $data
- * @return void
- */
- public function updateStats(array $data): void
- {
- $this->increment('request_count', $data['request_count'] ?? 1);
- if (isset($data['success']) && $data['success']) {
- $this->increment('success_count');
- } else {
- $this->increment('error_count');
- }
- if (isset($data['response_time'])) {
- $this->updateResponseTime($data['response_time']);
- }
- if (isset($data['rate_limit_hit']) && $data['rate_limit_hit']) {
- $this->increment('rate_limit_hits');
- }
- if (isset($data['unique_ip'])) {
- $this->updateUniqueIps($data['unique_ip']);
- }
- if (isset($data['error_details'])) {
- $this->updateErrorDetails($data['error_details']);
- }
- }
- /**
- * 更新响应时间统计
- *
- * @param float $responseTime
- * @return void
- */
- protected function updateResponseTime(float $responseTime): void
- {
- // 更新平均响应时间
- $totalTime = $this->avg_response_time * ($this->request_count - 1) + $responseTime;
- $this->avg_response_time = $totalTime / $this->request_count;
- // 更新最大响应时间
- if ($responseTime > $this->max_response_time) {
- $this->max_response_time = $responseTime;
- }
- // 更新最小响应时间
- if ($this->min_response_time === 0 || $responseTime < $this->min_response_time) {
- $this->min_response_time = $responseTime;
- }
- $this->save();
- }
- /**
- * 更新唯一IP统计
- *
- * @param string $ip
- * @return void
- */
- protected function updateUniqueIps(string $ip): void
- {
- // 这里可以使用Redis Set来精确统计唯一IP
- // 为了简化,这里只是增加计数
- $this->increment('unique_ips');
- }
- /**
- * 更新错误详情
- *
- * @param array $errorDetails
- * @return void
- */
- protected function updateErrorDetails(array $errorDetails): void
- {
- $currentDetails = $this->error_details ?? [];
- $errorCode = $errorDetails['code'] ?? 'unknown';
- if (!isset($currentDetails[$errorCode])) {
- $currentDetails[$errorCode] = [
- 'count' => 0,
- 'message' => $errorDetails['message'] ?? '',
- 'first_seen' => now()->toISOString(),
- ];
- }
- $currentDetails[$errorCode]['count']++;
- $currentDetails[$errorCode]['last_seen'] = now()->toISOString();
- $this->update(['error_details' => $currentDetails]);
- }
- /**
- * 按应用ID查询
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param string $appId
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeByApp($query, string $appId)
- {
- return $query->where('app_id', $appId);
- }
- /**
- * 按日期查询
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param string $date
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeByDate($query, string $date)
- {
- return $query->where('date', $date);
- }
- /**
- * 按日期范围查询
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param string $startDate
- * @param string $endDate
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeDateRange($query, string $startDate, string $endDate)
- {
- return $query->whereBetween('date', [$startDate, $endDate]);
- }
- /**
- * 按小时查询
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param int $hour
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeByHour($query, int $hour)
- {
- return $query->where('hour', $hour);
- }
- /**
- * 按接口端点查询
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param string $endpoint
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeByEndpoint($query, string $endpoint)
- {
- return $query->where('endpoint', $endpoint);
- }
- /**
- * 查询今日统计
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeToday($query)
- {
- return $query->where('date', now()->toDateString());
- }
- /**
- * 查询昨日统计
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeYesterday($query)
- {
- return $query->where('date', now()->subDay()->toDateString());
- }
- /**
- * 查询本周统计
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeThisWeek($query)
- {
- return $query->whereBetween('date', [
- now()->startOfWeek()->toDateString(),
- now()->endOfWeek()->toDateString()
- ]);
- }
- /**
- * 查询本月统计
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeThisMonth($query)
- {
- return $query->whereBetween('date', [
- now()->startOfMonth()->toDateString(),
- now()->endOfMonth()->toDateString()
- ]);
- }
- }
|