Skip to content
This repository was archived by the owner on Aug 1, 2022. It is now read-only.

fix(Prometheus-client): Return error message when using invalid query #81

Merged
merged 50 commits into from
Jul 19, 2022
Merged
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
c5836e9
feat: add promethus http api query client
Qinyouzeng Jun 14, 2022
c771526
feat: add test project
Qinyouzeng Jun 14, 2022
e39384e
feat: api query add
Qinyouzeng Jun 16, 2022
2923da4
feat: update code and add tests
Qinyouzeng Jun 17, 2022
cbde367
docs: add docs
Qinyouzeng Jun 17, 2022
3af77c1
feat: add convert json value to object
Qinyouzeng Jun 17, 2022
98cb7c9
feat: fix enume and comments
Qinyouzeng Jun 20, 2022
b659739
feat: code styles and other specifications update
Qinyouzeng Jun 21, 2022
743b82d
feat: update callerprovider inject
Qinyouzeng Jun 21, 2022
477691b
feat: update jsonelement convert to obj
Qinyouzeng Jun 21, 2022
89ed2eb
feat: update extensions
Qinyouzeng Jun 22, 2022
b21d163
feat: update internal to public
Qinyouzeng Jun 22, 2022
b57c468
feat: update directory
Qinyouzeng Jun 23, 2022
4496cea
feat: test refrence update
Qinyouzeng Jun 24, 2022
e2f5835
chore: comments and filename update
Qinyouzeng Jun 24, 2022
5c2d798
chore: remove not exists project id
Qinyouzeng Jun 28, 2022
d22d39c
chore: update docs and code style
Qinyouzeng Jun 28, 2022
9a747bb
chore: enums update
Qinyouzeng Jun 28, 2022
d942218
chore: doc code style update
Qinyouzeng Jun 30, 2022
39246f3
chore: dosc update
Qinyouzeng Jun 30, 2022
5a93140
chore: docs update
Qinyouzeng Jun 30, 2022
8e1c4b0
feat: add promethus http api query client
Qinyouzeng Jun 14, 2022
782fa15
feat: add test project
Qinyouzeng Jun 14, 2022
6a4ff0f
feat: api query add
Qinyouzeng Jun 16, 2022
99a0e1a
feat: update code and add tests
Qinyouzeng Jun 17, 2022
f7a571f
docs: add docs
Qinyouzeng Jun 17, 2022
64676e0
feat: add convert json value to object
Qinyouzeng Jun 17, 2022
fac4870
feat: fix enume and comments
Qinyouzeng Jun 20, 2022
d32c669
feat: code styles and other specifications update
Qinyouzeng Jun 21, 2022
7fa9168
feat: update callerprovider inject
Qinyouzeng Jun 21, 2022
5d8a1eb
feat: update jsonelement convert to obj
Qinyouzeng Jun 21, 2022
6c011e8
feat: update extensions
Qinyouzeng Jun 22, 2022
ed59bfb
feat: update internal to public
Qinyouzeng Jun 22, 2022
00fb2bc
feat: update directory
Qinyouzeng Jun 23, 2022
90b5e6f
feat: test refrence update
Qinyouzeng Jun 24, 2022
fef4606
chore: comments and filename update
Qinyouzeng Jun 24, 2022
7b33de8
chore: remove not exists project id
Qinyouzeng Jun 28, 2022
9952add
chore: update docs and code style
Qinyouzeng Jun 28, 2022
9847a88
chore: enums update
Qinyouzeng Jun 28, 2022
5c4dfe7
chore: doc code style update
Qinyouzeng Jun 30, 2022
d3822ae
chore: dosc update
Qinyouzeng Jun 30, 2022
5912f21
chore: docs update
Qinyouzeng Jun 30, 2022
2e5437a
Merge branch 'feature/promethus-query-client' of https://github.com/m…
Qinyouzeng Jun 30, 2022
e36ed26
chore: name update and remove no used files
Qinyouzeng Jun 30, 2022
f36051d
chore: folder name update
Qinyouzeng Jun 30, 2022
7ae8db6
chore: file rename
Qinyouzeng Jun 30, 2022
fcd3447
chore: class split
Qinyouzeng Jun 30, 2022
e48c968
feat: close thorw friendly exception
Qinyouzeng Jul 5, 2022
8fcff99
chore:merge
Qinyouzeng Jul 6, 2022
75e5a36
chore: code format
Qinyouzeng Jul 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: api query add
Qinyouzeng committed Jun 30, 2022
commit 6a4ff0f5e886956c28a658f90941592883e58bea
168 changes: 168 additions & 0 deletions Masa.Utils.Data.Promethus/Extenistion/HttpClientExtensition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
using Masa.Utils.Caller.Core;
using System.Collections;
using System.Reflection;
using System.Text;
using System.Web;

[assembly: InternalsVisibleTo("Masa.Utils.Data.Promethus.Test")]

namespace System.Net.Http;

internal static class HttpClientExtensition
{
public static async Task<string> GetAsync(this ICallerProvider caller, string url,object data)
{
var request=new HttpRequestMessage(HttpMethod.Get, $"{url}?{data?.ToUrlParam()}");
var response= await caller.SendAsync(request);
return await response.Content.ReadAsStringAsync();
}

/// <summary>
/// not support System.text.json
/// </summary>
/// <param name="obj"></param>
/// <param name="isEnumString"></param>
/// <param name="isCamelCase"></param>
/// <param name="isUrlEncode"></param>
/// <returns></returns>
public static string? ToUrlParam(this object obj, bool isEnumString = true, bool isCamelCase = true, bool isUrlEncode = true)
{
return GetValue(obj, string.Empty, isEnumString, isCamelCase, isUrlEncode);
}

private static string? GetValue(object obj, string preStr, bool isEnumString = false, bool isCamelCase = true, bool isUrlEncode = true)
{
if (obj == null) return null;
var type = obj.GetType();
if (type == typeof(string))//string
{
var str = (string)obj;
return AppendValue(preStr, str, "=", isUrlEncode);
}
else if (type.IsValueType)
{
if (type.IsEnum)//enum
{
var str = isEnumString ? obj.ToString() : Convert.ToInt32(obj).ToString();
return AppendValue(preStr, str, "=", isUrlEncode);
}
else if (!type.IsPrimitive) //struct
{
return GetObjValue(type, obj, preStr, isEnumString, isCamelCase, isUrlEncode);
}
else //sample value
{
var str = obj.ToString();
return AppendValue(preStr, str, "=", isUrlEncode);
}
}
else if (type.IsArray || type.GetInterfaces().Any(t => t.Name.IndexOf("IEnumerable") == 0))
{
return GetEnumerableValue(obj, preStr, isEnumString, isCamelCase, isUrlEncode);
}
else if (type.IsClass)
{
return GetObjValue(type, obj, preStr, isEnumString, isCamelCase, isUrlEncode);
}
else
{
//
return null;
}
}

private static string GetObjValue(Type type, object obj, string preStr, bool isEnumString = false, bool isCamelCase = true, bool isUrlEncode = true)
{
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField);
var list = new List<string>();
if (properties.Length > 0)
{
foreach (var item in properties)
{
var str = GetMemerInfoValue(item, item.GetValue(obj), preStr, isEnumString, isCamelCase, isUrlEncode);
if (string.IsNullOrEmpty(str))
continue;
list.Add(str);
}
}

if (fields.Length > 0)
{
foreach (var item in fields)
{
var str = GetMemerInfoValue(item, item.GetValue(obj), preStr, isEnumString, isCamelCase, isUrlEncode);
if (string.IsNullOrEmpty(str))
continue;
list.Add(str);
}
}

if (!list.Any())
return default!;
list.Sort();
return string.Join('&', list);
}

private static string? GetMemerInfoValue(MemberInfo info, object? value, string preStr, bool isEnumString = false, bool isCamelCase = true, bool isUrlEncode = true)
{
if (value == null)
return null;

var name = info.Name;
if (isCamelCase)
name = ToCamelCase(name);

return GetValue(value, AppendValue(preStr, name, ".", isUrlEncode) ?? default!, isEnumString, isCamelCase, isUrlEncode);
}

private static string? GetEnumerableValue(object obj, string preStr, bool isEnumString = false, bool isCamelCase = true, bool isUrlEncode = true)
{
StringBuilder builder = new StringBuilder(4096);
var list = new List<string>();
foreach (var item in (IEnumerable)obj)
{
if (item is KeyValuePair<string, object> keyValue)
{
var name = keyValue.Key;
if (isCamelCase)
name = ToCamelCase(name);
var str = GetValue(keyValue.Value, AppendValue(preStr, name, ".", isUrlEncode) ?? default!, isEnumString, isCamelCase, isUrlEncode);
if (!string.IsNullOrEmpty(str))
list.Add(str);
}
else
{
var str = GetValue(item, $"{preStr}{(isUrlEncode ? HttpUtility.UrlEncode("[]", Encoding.UTF8) : "[]")}", isEnumString, isCamelCase, isUrlEncode);
if (!string.IsNullOrEmpty(str))
list.Add(str);
}
}
if (!list.Any())
return default!;
list.Sort();
return string.Join('&', list);
}

private static string? AppendValue(string preStr, string? value, string splitChar, bool isUrlEncode)
{
if (string.IsNullOrEmpty(preStr) || string.IsNullOrEmpty(value))
return value;
if (isUrlEncode)
return $"{preStr}{splitChar}{HttpUtility.UrlEncode(value, Encoding.UTF8)}";
else
return $"{preStr}{splitChar}{value}";
}

public static string ToCamelCase(this string str)
{
if (string.IsNullOrEmpty(str)) return str;
var c = str[0];
if (c - 'A' >= 0 && c - 'Z' <= 0)
return $"{(char)(c + 32)}{str.AsSpan().Slice(1)}";

return str;
}
}
4 changes: 4 additions & 0 deletions Masa.Utils.Data.Promethus/Masa.Utils.Data.Promethus.csproj
Original file line number Diff line number Diff line change
@@ -6,4 +6,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\src\Caller\Masa.Utils.Caller.Core\Masa.Utils.Caller.Core.csproj" />
</ItemGroup>

</Project>
75 changes: 63 additions & 12 deletions Masa.Utils.Data.Promethus/MasaPromethusClient.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,90 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

using Masa.Utils.Caller.Core;
using System.Text.Json;

[assembly: InternalsVisibleTo("Masa.Utils.Data.Promethus.Test")]

namespace Masa.Utils.Data.Promethus;

internal class MasaPromethusClient : IMasaPromethusClient
{
public Task<ResponseExemplarResultModel> ExemplarQueryAsync(RequestQueryModel query)
private readonly ICallerProvider _caller;
private static JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};

public MasaPromethusClient(ICallerProvider caller)
{
_caller = caller;
}

public async Task<ResponseExemplarResultModel> ExemplarQueryAsync(RequestQueryModel query)
{
throw new NotImplementedException();
return await QueryDataAsync<ResponseExemplarResultModel>("/api/v1/query_exemplars", query);
}

public Task<ResponseLabelResultModel> LabelsQueryAsync(RequestMetaDataQueryModel query)
public async Task<ResponseLabelResultModel> LabelsQueryAsync(RequestMetaDataQueryModel query)
{
throw new NotImplementedException();
return await QueryDataAsync<ResponseLabelResultModel>("/api/v1/labels", query);
}

public Task<ResponseLabelResultModel> LabelValuesQueryAsync(RequestMetaDataQueryModel query)
public async Task<ResponseLabelResultModel> LabelValuesQueryAsync(RequestMetaDataQueryModel query)
{
throw new NotImplementedException();
return await QueryDataAsync<ResponseLabelResultModel>("/api/v1/label/<label_name>/values", query);
}

public Task<ResponseQueryResultCommonModel> QueryAsync(RequestQueryModel query)
public async Task<ResponseQueryResultCommonModel> QueryAsync(RequestQueryModel query)
{
throw new NotImplementedException();
return await QueryDataAsync<ResponseQueryResultCommonModel>("/api/v1/query", query);
}

public Task<ResponseQueryResultCommonModel> QueryRangeAsync(RequestQueryRangeModel query)
public async Task<ResponseQueryResultCommonModel> QueryRangeAsync(RequestQueryRangeModel query)
{
throw new NotImplementedException();
return await QueryDataAsync<ResponseQueryResultCommonModel>("/api/v1/query_range", query);
}

public Task<ResponseSerieResultModel> SeriesAsync(RequestMetaDataQueryModel query)
public async Task<ResponseSerieResultModel> SeriesAsync(RequestMetaDataQueryModel query)
{
throw new NotImplementedException();
return await QueryDataAsync<ResponseSerieResultModel>("/api/v1/series", query);
}

private async Task<T> QueryDataAsync<T>(string url, object data) where T : ResponseResultBaseModel
{
var str = await _caller.GetAsync(url, data);
if (string.IsNullOrEmpty(str))
return default!;

var baseResult = JsonSerializer.Deserialize<T>(str, _jsonSerializerOptions);
if (baseResult == null || baseResult.Status != ResultStatuses.Success)
{
return baseResult ?? default!;
}

if (typeof(T) == typeof(ResponseQueryResultCommonModel))
{
var result = baseResult as ResponseQueryResultCommonModel;
if (result == null || result.Data == null)
return baseResult;
switch (result.Data.ResultType)
{
case ResultTypes.Matrix:
{
var temp = JsonSerializer.Serialize(result.Data.Result, _jsonSerializerOptions);
result.Data.Result = JsonSerializer.Deserialize<MatrixRangeModel[]>(temp, _jsonSerializerOptions);
return result as T ?? default!;
}
case ResultTypes.Vector:
{
var temp = JsonSerializer.Serialize(result.Data.Result, _jsonSerializerOptions);
result.Data.Result = JsonSerializer.Deserialize<InstantVectorModel[]>(temp, _jsonSerializerOptions);
return result as T ?? default!;
}
}
}

return baseResult;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.Utils.Data.Promethus.Model;

public class RequestLableValueQueryModel: RequestMetaDataQueryModel
{
public string Lable { get; set; } = "__name__";
}
13 changes: 13 additions & 0 deletions src/Data/Masa.Utils.Data.Elasticsearch/MappingConst.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.Utils.Data.Elasticsearch;

internal class MappingConst
{
public const string PROPERTY = "properties";
public const string TYPE = "type";
public const string FIELD = "fields";
public const string MAXLENGTH = "ignore_above";
public const string KEYWORD = "keyword";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.Utils.Data.Elasticsearch.Response;

public class MappingResponse
{
public string? Name { get; set; }

public string? DataType { get; set; }

public bool? IsKeyword { get; set; }

public int? MaxLenth { get; set; }
}
Loading