init
This commit is contained in:
8
Services/ILokiService.cs
Normal file
8
Services/ILokiService.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using GetFromLoki.Models;
|
||||
|
||||
namespace GetFromLoki.Services;
|
||||
|
||||
public interface ILokiService
|
||||
{
|
||||
Task<List<LogEntry>> GetLogsAsync(LogQueryRequest request);
|
||||
}
|
||||
7
Services/LokiOptions.cs
Normal file
7
Services/LokiOptions.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace GetFromLoki.Services;
|
||||
|
||||
public class LokiOptions
|
||||
{
|
||||
public string BaseUrl { get; set; } = "http://localhost:3100";
|
||||
public int QueryTimeout { get; set; } = 30;
|
||||
}
|
||||
113
Services/LokiService.cs
Normal file
113
Services/LokiService.cs
Normal file
@ -0,0 +1,113 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user