Files
get-from-loki/Services/LokiService.cs
2025-08-21 14:56:35 +05:00

114 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text.Json;
using GetFromLoki.Models;
using Microsoft.Extensions.Options;
namespace GetFromLoki.Services;
public class LokiService : ILokiService
{
private readonly HttpClient _httpClient;
private readonly LokiOptions _options;
public LokiService(HttpClient httpClient, IOptions<LokiOptions> options)
{
_httpClient = httpClient;
_options = options.Value;
_httpClient.BaseAddress = new Uri(_options.BaseUrl);
_httpClient.Timeout = TimeSpan.FromSeconds(_options.QueryTimeout);
}
public async Task<List<LogEntry>> GetLogsAsync(LogQueryRequest request)
{
var logs = new List<LogEntry>();
// Формируем LogQL запрос
var query = BuildLogQLQuery(request);
// Формируем URL с параметрами
var queryParams = new List<string>
{
$"query={Uri.EscapeDataString(query)}",
$"limit={request.Limit ?? 100}"
};
if (request.StartTime.HasValue)
{
var startTimeNs = ((DateTimeOffset)request.StartTime.Value).ToUnixTimeMilliseconds() * 1_000_000;
queryParams.Add($"start={startTimeNs}");
}
if (request.EndTime.HasValue)
{
var endTimeNs = ((DateTimeOffset)request.EndTime.Value).ToUnixTimeMilliseconds() * 1_000_000;
queryParams.Add($"end={endTimeNs}");
}
var url = $"/loki/api/v1/query_range?{string.Join("&", queryParams)}";
try
{
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
var lokiResponse = JsonSerializer.Deserialize<LokiQueryResponse>(
jsonResponse,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
);
if (lokiResponse?.Data?.Result != null)
{
foreach (var result in lokiResponse.Data.Result)
{
foreach (var value in result.Values)
{
if (value.Count >= 2)
{
// Loki возвращает timestamp в наносекундах
if (long.TryParse(value[0], out var timestampNs))
{
var timestamp = DateTimeOffset.FromUnixTimeMilliseconds(timestampNs / 1000000).DateTime;
logs.Add(new LogEntry
{
Timestamp = timestamp,
Message = value[1]
});
}
}
}
}
}
}
catch (Exception ex)
{
throw new InvalidOperationException($"Ошибка при получении логов из Loki: {ex.Message}", ex);
}
return logs.OrderBy(l => l.Timestamp).ToList();
}
private static string BuildLogQLQuery(LogQueryRequest request)
{
var query = "{";
var conditions = new List<string>();
// Добавляем все лейблы
foreach (var label in request.Labels)
{
if (!string.IsNullOrEmpty(label.Value))
{
conditions.Add($"{label.Key}=\"{label.Value}\"");
}
else
{
conditions.Add($"{label.Key}!=\"\"");
}
}
query += string.Join(",", conditions);
query += "}";
return query;
}
}