Files
Aptabase-WPF-sdk/src/AptabaseClientBase.cs
정나래 3475a7b988 [변경] AptabaseClient.cs
- 종료 직전에 보내는 Event 누락 방지하기 위한 코드 수정
  : 큐에 이벤트를 추가하면 +1, 큐에서 읽어와서 Event를 Send하면 -1하는 필드 추가
  : 필드가 0이되기를 기다리는 함수 추가(대기 한계 시간 기본값 1500ms)

[변경] AptabaseClientBase.cs
- EventData에 ipAddredd 할당하는 코드 제거
 : 매번 API 호출하면서 속도 지연의 원인이 됨
- aptabase-debug.log 파일 생성하는 코드 제거
 : 파일 관리가 안되고 있으므로 제거
2025-09-12 17:47:24 +09:00

163 lines
4.8 KiB
C#

using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Reflection;
using System.Threading.Tasks;
namespace Aptabase.WPF;
internal class AptabaseClientBase : IAsyncDisposable
{
protected static readonly TimeSpan SESSION_TIMEOUT = TimeSpan.FromMinutes(60);
private static readonly Random _random = new();
private readonly ILogger? _logger;
private readonly HttpClient? _http;
private static readonly HttpClient _ipClient = new();
private DateTime _lastTouched = DateTime.UtcNow;
private string _sessionId = NewSessionId();
private static readonly SystemInfo _sysInfo = new();
private static readonly Dictionary<string, string> _hosts = new()
{
{ "US", "https://us.aptabase.com" },
{ "EU", "https://eu.aptabase.com" },
{ "DEV", "https://localhost:3000" },
{ "SH", "" },
};
public AptabaseClientBase(string appKey, AptabaseOptions? options, ILogger? logger)
{
_logger = logger;
var parts = appKey.Split("-");
if (parts.Length != 3 || !_hosts.ContainsKey(parts[1]))
{
_logger?.LogWarning("The Aptabase App Key {AppKey} is invalid. Tracking will be disabled.", appKey);
return;
}
var region = parts[1];
var baseUrl = GetBaseUrl(parts[1], options);
if (baseUrl is null)
{
return;
}
_sysInfo.IsDebug = options?.IsDebugMode ?? SystemInfo.IsInDebugMode(Assembly.GetExecutingAssembly());
_http = region == "DEV" ? new(new LocalHttpsClientHandler()) : new();
_http.BaseAddress = new Uri(baseUrl);
_http.DefaultRequestHeaders.Add("App-Key", appKey);
}
internal async Task TrackEvent(EventData eventData)
{
if (_http is null)
{
return;
}
RefreshSession();
eventData.SessionId = _sessionId;
eventData.SystemProps = _sysInfo;
if (eventData.Props is null)
eventData.Props = new Dictionary<string, object>();
//eventData.Props["ipAddress"] = await GetPublicIpAddress(); 느려서 제외. 필요하면 다른 방법 사용 요망
var body = JsonContent.Create(eventData);
var response = await _http.PostAsync("/api/v0/event", body);
//var logPath = "aptabase-debug.log"; //파일 관리 안되므로 제거. 필요하면 다른 방법 사용 요망
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode >= HttpStatusCode.InternalServerError ||
response.StatusCode == HttpStatusCode.RequestTimeout ||
response.StatusCode == HttpStatusCode.TooManyRequests)
{
// throw error, should be retried
response.EnsureSuccessStatusCode();
}
var responseBody = await response.Content.ReadAsStringAsync();
_logger?.LogError("Failed to perform TrackEvent due to {StatusCode} and response body {Body}", response.StatusCode, responseBody);
//File.AppendAllText(logPath, $"{eventData.EventName} Failed to perform TrackEvent due to {response.StatusCode} and response body {responseBody}\n");
}
else
{ var responseBody = await response.Content.ReadAsStringAsync();
//File.AppendAllText(logPath, $"{eventData.EventName} TrackEvent successful with response body {responseBody}\n");
}
}
private async Task<string> GetPublicIpAddress()
{
try
{
return await _ipClient.GetStringAsync("https://api.ipify.org");
}
catch
{
return "unknown";
}
}
public virtual ValueTask DisposeAsync()
{
_http?.Dispose();
return ValueTask.CompletedTask;
}
private void RefreshSession()
{
var now = DateTime.UtcNow;
var timeSince = now.Subtract(_lastTouched);
if (timeSince >= SESSION_TIMEOUT)
{
_sessionId = NewSessionId();
}
_lastTouched = now;
}
private static string NewSessionId()
{
var epochInSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var random = _random.NextInt64(0, 99999999);
return (epochInSeconds * 100000000 + random).ToString();
}
private string? GetBaseUrl(string region, AptabaseOptions? options)
{
if (region == "SH")
{
if (string.IsNullOrEmpty(options?.Host))
{
_logger?.LogWarning("Host parameter must be defined when using Self-Hosted App Key. Tracking will be disabled.");
return null;
}
return options.Host;
}
return _hosts[region];
}
}