| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- using dodohold.core;
- using Microsoft.AspNetCore.Mvc;
- using molilian.core;
- using System.Text.Json;
- namespace molilian.api.Controllers
- {
- [ApiController]
- [MyAuthorize("admin")]
- [Route("api/[controller]/[action]")]
- public class DeeplinkReportController : ControllerBase
- {
- private const int MaxRangeDays = 90;
- readonly IAuthorizationProvider provider = new AdminProvider();
- protected IHttpContextAccessor _accessor;
- public DeeplinkReportController(IHttpContextAccessor accessor)
- {
- _accessor = accessor;
- }
- [HttpPost]
- public async Task<ActionResult> daily([FromBody] JsonElement form)
- {
- _ = provider.Get(_accessor.HttpContext);
- var queryDate = form.PathReadArray<string>("query_date[]");
- var channelName = form.Read("channel_name", string.Empty).Trim();
- DateTime start = DateTime.Now.Date.AddDays(-6);
- DateTime end = DateTime.Now.Date;
- if (queryDate.Count == 2)
- {
- if (DateTime.TryParse(queryDate[0], out var parsedStart))
- {
- start = parsedStart.Date;
- }
- if (DateTime.TryParse(queryDate[1], out var parsedEnd))
- {
- end = parsedEnd.Date;
- }
- }
- if (end < start)
- {
- (start, end) = (end, start);
- }
- if ((end - start).TotalDays >= MaxRangeDays)
- {
- end = start.AddDays(MaxRangeDays - 1);
- }
- var accountName = string.IsNullOrWhiteSpace(channelName)
- ? "tool"
- : channelName;
- var reportChannels = GetReportChannels(channelName);
- var channelNames = reportChannels
- .Select(item => item.channel_name)
- .ToList();
- var channelTotals = channelNames.ToDictionary(
- item => item,
- _ => 0L,
- StringComparer.OrdinalIgnoreCase
- );
- var dailyRows = new List<DeeplinkDailyReportRow>();
- for (var date = start; date <= end; date = date.AddDays(1))
- {
- var dateKey = date.ToString("yyyyMMdd");
- var channelStats = await GetChannelStatsAsync(reportChannels, dateKey);
- foreach (var item in channelStats)
- {
- channelTotals[item.channel_name] += item.total_count;
- }
- var reportDate = date.ToString("yyyy-MM-dd");
- var accountTotalCount = await TkLogCore.GetTotalAsync($":parse_total:{accountName}:{dateKey}");
- var row = new DeeplinkDailyReportRow
- {
- row_key = reportDate,
- row_type = "daily",
- report_date = reportDate,
- request_count = accountTotalCount,
- total_count = accountTotalCount,
- success_count = await TkLogCore.GetTotalAsync($":parse_total:{accountName}:success:{dateKey}"),
- fail_count = await TkLogCore.GetTotalAsync($":parse_total:{accountName}:fail:{dateKey}")
- };
- row.children = channelStats
- .Select(item => new DeeplinkDailyReportRow
- {
- row_key = $"{reportDate}:{item.channel_name}",
- row_type = "channel",
- report_date = item.display_name,
- channel_name = item.channel_name,
- display_name = item.display_name,
- request_count = item.request_count,
- total_count = item.total_count,
- success_count = item.success_count,
- fail_count = item.fail_count
- })
- .ToList();
- dailyRows.Add(row);
- }
- var channels = channelTotals
- .Where(item => !string.IsNullOrWhiteSpace(channelName) || item.Value > 0)
- .OrderByDescending(item => item.Value)
- .ThenBy(item => item.Key)
- .Select(item => new DeeplinkDailyReportChannel
- {
- channel_name = item.Key,
- display_name = GetDisplayName(reportChannels, item.Key),
- request_count = item.Value,
- total_count = item.Value
- })
- .ToList();
- var activeChannelNames = channels
- .Select(item => item.channel_name)
- .ToHashSet(StringComparer.OrdinalIgnoreCase);
- foreach (var row in dailyRows)
- {
- row.children = (row.children ?? new List<DeeplinkDailyReportRow>())
- .Where(item => activeChannelNames.Contains(item.channel_name))
- .OrderByDescending(item => item.total_count)
- .ThenBy(item => item.channel_name)
- .ToList();
- if (!row.children.Any())
- {
- row.children = null;
- }
- }
- var list = dailyRows
- .OrderByDescending(item => item.report_date)
- .ToList();
- var summary = new DeeplinkDailyReportSummary
- {
- request_count = list.Sum(item => item.request_count),
- total_count = list.Sum(item => item.total_count),
- success_count = list.Sum(item => item.success_count),
- fail_count = list.Sum(item => item.fail_count)
- };
- return new APIResult(new
- {
- data = new
- {
- list,
- count = list.Count,
- summary,
- channels,
- maxRangeDays = MaxRangeDays
- }
- });
- }
- private static List<DeeplinkDailyReportChannel> GetReportChannels(string channelName)
- {
- var channels = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
- try
- {
- var rules = new DBContext.Table("deeplink_parse_rule")
- .Where("status=@status", new { status = 1 })
- .Select<DeeplinkParseRuleDTO>();
- if (rules != null)
- {
- foreach (var rule in rules)
- {
- AddChannel(channels, rule.channel_name, rule.name);
- }
- }
- }
- catch
- {
- // Channel names are display metadata. Redis statistics remain usable if this lookup fails.
- }
- if (!string.IsNullOrWhiteSpace(channelName))
- {
- AddChannel(channels, channelName, channelName);
- }
- else
- {
- foreach (var name in Enum.GetNames(typeof(TkChannelEnum)))
- {
- AddChannel(channels, name, name);
- }
- }
- return channels
- .OrderBy(item => item.Key)
- .Select(item => new DeeplinkDailyReportChannel
- {
- channel_name = item.Key,
- display_name = item.Value
- })
- .ToList();
- }
- private static void AddChannel(
- Dictionary<string, string> channels,
- string channelName,
- string displayName
- )
- {
- if (string.IsNullOrWhiteSpace(channelName)) return;
- var normalizedChannel = channelName.Trim();
- if (normalizedChannel.Equals("all", StringComparison.OrdinalIgnoreCase)) return;
- if (normalizedChannel.Equals("tool", StringComparison.OrdinalIgnoreCase)) return;
- if (normalizedChannel.Equals("unknown", StringComparison.OrdinalIgnoreCase)) return;
- var normalizedDisplay = string.IsNullOrWhiteSpace(displayName)
- ? normalizedChannel
- : displayName.Trim();
- if (!channels.ContainsKey(normalizedChannel) ||
- channels[normalizedChannel].Equals(normalizedChannel, StringComparison.OrdinalIgnoreCase))
- {
- channels[normalizedChannel] = normalizedDisplay;
- }
- }
- private static string GetDisplayName(
- List<DeeplinkDailyReportChannel> channels,
- string channelName
- )
- {
- return channels
- .FirstOrDefault(item => item.channel_name.Equals(
- channelName,
- StringComparison.OrdinalIgnoreCase
- ))
- ?.display_name ?? channelName;
- }
- private static async Task<List<DeeplinkDailyReportChannel>> GetChannelStatsAsync(
- List<DeeplinkDailyReportChannel> channels,
- string dateKey
- )
- {
- var tasks = channels.Select(async channel =>
- {
- var channelTotalCount = await TkLogCore.GetTotalAsync($":parse_total:{channel.channel_name}:{dateKey}");
- return new DeeplinkDailyReportChannel
- {
- channel_name = channel.channel_name,
- display_name = channel.display_name,
- request_count = channelTotalCount,
- total_count = channelTotalCount,
- success_count = await TkLogCore.GetTotalAsync($":parse_total:{channel.channel_name}:success:{dateKey}"),
- fail_count = await TkLogCore.GetTotalAsync($":parse_total:{channel.channel_name}:fail:{dateKey}")
- };
- });
- var results = await Task.WhenAll(tasks);
- return results.ToList();
- }
- }
- public class DeeplinkDailyReportChannel
- {
- public string channel_name { get; set; } = string.Empty;
- public string display_name { get; set; } = string.Empty;
- public long request_count { get; set; } = 0;
- public long total_count { get; set; } = 0;
- public long success_count { get; set; } = 0;
- public long fail_count { get; set; } = 0;
- }
- public class DeeplinkDailyReportRow
- {
- public string row_key { get; set; } = string.Empty;
- public string row_type { get; set; } = "daily";
- public string report_date { get; set; } = string.Empty;
- public string channel_name { get; set; } = string.Empty;
- public string display_name { get; set; } = string.Empty;
- public long request_count { get; set; } = 0;
- public long total_count { get; set; } = 0;
- public long success_count { get; set; } = 0;
- public long fail_count { get; set; } = 0;
- public List<DeeplinkDailyReportRow>? children { get; set; }
- }
- public class DeeplinkDailyReportSummary
- {
- public long request_count { get; set; } = 0;
- public long total_count { get; set; } = 0;
- public long success_count { get; set; } = 0;
- public long fail_count { get; set; } = 0;
- }
- }
|