TracksController.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using molilian.core;
  2. using dodohold.core;
  3. using Microsoft.AspNetCore.Http.Features;
  4. using Microsoft.AspNetCore.Mvc;
  5. using System.Text.Json;
  6. using TencentCloud.Ecm.V20190719.Models;
  7. using YunhuiKit;
  8. namespace molilian.api.Controllers
  9. {
  10. [ApiController]
  11. [Route("[controller]/[action]")]
  12. public class TracksController : ControllerBase
  13. {
  14. protected IHttpContextAccessor _accessor;
  15. public TracksController(IHttpContextAccessor accessor)
  16. {
  17. _accessor = accessor;
  18. }
  19. [HttpGet]
  20. public async Task<ActionResult> Track([FromQuery] string? track_id = null, [FromQuery] string? unique_id = null, [FromQuery] string? scene = "", [FromQuery] string? account_id = null)
  21. {
  22. bool validTrackId = int.TryParse(track_id, out int parsedTrackId) && parsedTrackId > 0;
  23. int parsedAccountId = 0;
  24. bool validAccountId = string.IsNullOrWhiteSpace(account_id) || int.TryParse(account_id, out parsedAccountId);
  25. parsedAccountId = validAccountId ? Math.Max(parsedAccountId, 0) : 0;
  26. string requestUniqueId = unique_id ?? string.Empty;
  27. string requestScene = scene ?? string.Empty;
  28. await WriteTrackRequestTextLogAsync(track_id, unique_id, scene, account_id, parsedTrackId, validTrackId, parsedAccountId, validAccountId);
  29. if (!validTrackId)
  30. {
  31. return new APIResult(new { success = false, message = "miss" });
  32. }
  33. var link = await TracksCore.GetLinkByIdAsync(parsedTrackId);
  34. if (link == null)
  35. {
  36. return new APIResult(new { success = false, message = "not found" });
  37. }
  38. string trackScene = TracksCore.ResolveMetricScene(link, requestScene);
  39. var dto = new TrackRequestLogDTO
  40. {
  41. track_id = parsedTrackId,
  42. account_id = parsedAccountId,
  43. event_type = link.event_type,
  44. platform = link.platform,
  45. typename = link.typename,
  46. scene = trackScene,
  47. unique_id = requestUniqueId,
  48. ip = _accessor.HttpContext?.GetUserIp() ?? string.Empty,
  49. user_agent = Request.Headers.UserAgent.ToString(),
  50. referer = Request.Headers.Referer.ToString()
  51. };
  52. _ = TracksCore.LogTrackRequestAsync(dto);
  53. _ = TracksCore.TrackAsync(link, trackScene, parsedAccountId);
  54. return new APIResult(new { success = true, message = "ok" });
  55. }
  56. [HttpPost]
  57. public async Task<ActionResult> Create([FromQuery] string eventType, [FromQuery] string platform = "", [FromQuery] string typename = "", [FromQuery] string scene = "", [FromQuery] string uniqueId = "", [FromQuery] string description = "")
  58. {
  59. if (string.IsNullOrWhiteSpace(typename)) typename = platform;
  60. if (string.IsNullOrWhiteSpace(platform)) platform = typename;
  61. var link = await TracksCore.CreateLinkAsync(eventType, platform, typename, scene, uniqueId, description);
  62. if (link == null)
  63. {
  64. return new APIResult(new { success = false, message = "invalid params or eventType" });
  65. }
  66. //var request = _accessor.HttpContext!.Request;
  67. //string url = $"{request.Scheme}://{request.Host}{link.path}";
  68. return new APIResult(new { success = true, message = "ok", url = link.path });
  69. }
  70. [HttpGet]
  71. public async Task<ActionResult> Daily([FromQuery] int daysAgo = 0, [FromQuery] string reportDate = "", [FromQuery] bool includeToday = true, [FromQuery] bool includeYesterday = true)
  72. {
  73. var dates = new List<DateTime>();
  74. DateTime today = DateTime.Now.Date;
  75. if (!string.IsNullOrWhiteSpace(reportDate) && DateTime.TryParse(reportDate, out var parsed))
  76. {
  77. dates.Add(parsed.Date);
  78. if (includeToday && parsed.Date != today) dates.Add(today);
  79. }
  80. else
  81. {
  82. if (daysAgo > 0)
  83. {
  84. var date = today.AddDays(-daysAgo);
  85. dates.Add(date);
  86. if (includeToday && date != today) dates.Add(today);
  87. }
  88. else
  89. {
  90. dates.Add(today);
  91. if (includeYesterday) dates.Add(today.AddDays(-1));
  92. }
  93. }
  94. int rows = 0;
  95. var reportDates = new List<string>();
  96. var details = new List<object>();
  97. foreach (var date in dates.Distinct())
  98. {
  99. int dateRows = await TracksCore.FlushDailyAsync(date);
  100. rows += dateRows;
  101. reportDates.Add(date.ToString("yyyy-MM-dd"));
  102. details.Add(new { reportDate = date.ToString("yyyy-MM-dd"), rows = dateRows });
  103. }
  104. return new APIResult(new { success = true, message = "ok", rows, reportDates, details });
  105. }
  106. private async Task WriteTrackRequestTextLogAsync(
  107. string? rawTrackId,
  108. string? rawUniqueId,
  109. string? rawScene,
  110. string? rawAccountId,
  111. int parsedTrackId,
  112. bool validTrackId,
  113. int parsedAccountId,
  114. bool validAccountId)
  115. {
  116. try
  117. {
  118. string rawTarget = HttpContext.Features.Get<IHttpRequestFeature>()?.RawTarget ?? $"{Request.Path}{Request.QueryString}";
  119. string rawQuery = string.Empty;
  120. int rawQueryIndex = rawTarget.IndexOf('?');
  121. if (rawQueryIndex >= 0 && rawQueryIndex < rawTarget.Length - 1)
  122. {
  123. rawQuery = rawTarget[(rawQueryIndex + 1)..];
  124. }
  125. var logItem = new
  126. {
  127. time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
  128. method = Request.Method,
  129. scheme = Request.Scheme,
  130. host = Request.Host.Value,
  131. path = Request.Path.Value ?? string.Empty,
  132. raw_target = rawTarget,
  133. raw_query = rawQuery,
  134. raw_query_string = Request.QueryString.Value ?? string.Empty,
  135. query = Request.Query.ToDictionary(item => item.Key, item => item.Value.ToArray()),
  136. bound = new
  137. {
  138. track_id = rawTrackId ?? string.Empty,
  139. unique_id = rawUniqueId ?? string.Empty,
  140. scene = rawScene ?? string.Empty,
  141. account_id = rawAccountId ?? string.Empty
  142. },
  143. parsed = new
  144. {
  145. track_id = parsedTrackId,
  146. track_id_valid = validTrackId,
  147. account_id = parsedAccountId,
  148. account_id_valid = validAccountId
  149. },
  150. ip = _accessor.HttpContext?.GetUserIp() ?? string.Empty,
  151. remote_ip = HttpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty,
  152. x_forwarded_for = Request.Headers["X-Forwarded-For"].ToString(),
  153. x_original_url = Request.Headers["X-Original-URL"].ToString(),
  154. x_rewrite_url = Request.Headers["X-Rewrite-URL"].ToString(),
  155. user_agent = Request.Headers.UserAgent.ToString(),
  156. referer = Request.Headers.Referer.ToString()
  157. };
  158. await new LoggerLibrary("tracks", "track_request")
  159. .Info(JsonSerializer.Serialize(logItem))
  160. .SaveAsync();
  161. }
  162. catch (Exception ex)
  163. {
  164. _ = new LoggerLibrary("tracks", "track_request_error")
  165. .Info(ex.Message, ex.StackTrace)
  166. .SaveAsync();
  167. }
  168. }
  169. }
  170. }