初始化

This commit is contained in:
2025-11-26 11:18:26 +08:00
commit 0564b8c1f3
579 changed files with 346253 additions and 0 deletions

15
.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
#Visual Studio cache files
.vs/
# Build results
[Dd]ebug/
[Rr]elease/
Aliyun.Api.LogService/obj/
COMMON/obj/
DB_Server/obj/
Models/obj/
SERVER/obj/
TcpServer/obj/
WebUI/obj/
WebUI/App_Data/Log/

View File

@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<LangVersion>7.1</LangVersion>
<PackageId>Aliyun.SLS.SDK</PackageId>
<Authors>Aliyun SLS</Authors>
<NeutralLanguage>zh-CN</NeutralLanguage>
<PackageLicenseUrl>https://raw.githubusercontent.com/aliyun/aliyun-log-dotnetcore-sdk/master/LICENSE</PackageLicenseUrl>
<Owners>Aliyun SLS</Owners>
<PackageProjectUrl>https://github.com/aliyun/aliyun-log-dotnetcore-sdk</PackageProjectUrl>
<PackageTags>Aliyun </PackageTags>
<Title>Aliyun LogService .Net Core SDK</Title>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>1.1.1</PackageVersion>
<Description>Aliyun LogService SDK for .NET Core.</Description>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(OS)' == 'Release|Windows_NT' ">
<SignAssembly>true</SignAssembly>
<PublicSign>false</PublicSign>
<AssemblyOriginatorKeyFile>$(SolutionDir)\aliyun-log-dotnetcore-sdk.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
<SignAssembly>False</SignAssembly>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.20.1" />
<PackageReference Include="Iconic.Zlib.Netstandard" Version="1.0.0" />
<PackageReference Include="JetBrains.Annotations" Version="11.1.0" />
<PackageReference Include="lz4net" Version="1.0.15.93" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.4" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="System.Net.Http" Version="4.3.3" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_LastSelectedProfileId>D:\CW\RD_WEB\陈伟\Work\HotelServices_v1\HotelServices\Aliyun.Api.LogService\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,127 @@
//
// ConfigInputDetailInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Aliyun.Api.LogService.Domain.Config
{
public class ConfigInputDetailInfo
{
public const Boolean DefaultPreserve = true;
/// <summary>
/// 日志类型,现在只支持 common_reg_log。
/// </summary>
public String LogType { get; }
/// <summary>
/// 日志所在的父目录,例如 /var/logs/。
/// </summary>
public String LogPath { get; }
/// <summary>
/// 日志文件的Pattern例如 access*.log。
/// </summary>
public String FilePattern { get; }
/// <summary>
/// 是否打开本地缓存,在服务端之间链路断开的情况下,本地可以缓存 1GB 日志。
/// </summary>
public Boolean LocalStorage { get; }
/// <summary>
/// 日志时间格式, 如 %Y/%m/%d %H:%M:%S。
/// </summary>
public String TimeFormat { get; }
/// <summary>
/// 日志首行特征(正则表达式),由于匹配多行日志组成一条 log 的情况。
/// </summary>
public String LogBeginRegex { get; }
/// <summary>
/// 日志对提取正则表达式。
/// </summary>
public String Regex { get; }
/// <summary>
/// 日志提取后所生成的 Key。
/// </summary>
public IList<String> Key { get; }
/// <summary>
/// 用于过滤日志所用到的 key只有 key 的值满足对应 filterRegex 列中设定的正则表达式日志才是符合要求的。
/// </summary>
public IList<String> FilterKey { get; }
/// <summary>
/// 和每个 filterKey 对应的正则表达式, filterRegex 的长度和 filterKey 的长度必须相同。
/// </summary>
public IList<String> FilterRegex { get; }
/// <summary>
/// Topic 生成方式,支持以下四种类型:
/// <list type="bullet">
/// <item><description>用于将日志文件路径的某部分作为 topic如 /var/log/(.*).log。</description></item>
/// <item><description>none表示 topic 为空。</description></item>
/// <item><description>default表示将日志文件路径作为 topic。</description></item>
/// <item><description>group_topic表示将应用该配置的机器组 topic 属性作为 topic。</description></item>
/// </list>
/// </summary>
public String TopicFormat { get; set; }
/// <summary>
/// true 代表监控目录永不超时false 代表监控目录 30 分钟超时,默认值为 true。
/// </summary>
public Boolean Preserve { get; set; } = DefaultPreserve;
/// <summary>
/// 当设置 preserve 为 false 时,指定监控不超时目录的深度,最大深度支持 3。
/// </summary>
public Int32 PreserveDepth { get; set; }
/// <summary>
/// 支持两种类型utf8、gbk。
/// </summary>
public String FileEncoding { get; set; }
public ConfigInputDetailInfo(String logType, String logPath, String filePattern, Boolean localStorage, String timeFormat, String logBeginRegex, String regex, IEnumerable<String> key, IEnumerable<String> filterKey, IEnumerable<String> filterRegex)
{
this.LogType = logType;
this.LogPath = logPath;
this.FilePattern = filePattern;
this.LocalStorage = localStorage;
this.TimeFormat = timeFormat;
this.LogBeginRegex = logBeginRegex;
this.Regex = regex;
this.Key = key?.ToList();
this.FilterKey = filterKey?.ToList();
this.FilterRegex = filterRegex?.ToList();
}
}
}

View File

@@ -0,0 +1,40 @@
//
// ConfigOutputDetailInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.Config
{
public class ConfigOutputDetailInfo
{
public String LogstoreName { get; }
public ConfigOutputDetailInfo(String logstoreName)
{
this.LogstoreName = logstoreName;
}
}
}

View File

@@ -0,0 +1,73 @@
//
// CreateConfigRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Config
{
public class CreateConfigRequest : ProjectScopedRequest
{
/// <summary>
/// 日志配置名称, Project 下唯一。
/// </summary>
public String ConfigName { get; }
/// <summary>
/// 输入类型,现在只支持 file。
/// </summary>
public String InputType { get; }
/// <summary>
/// 输入详情。
/// </summary>
public ConfigInputDetailInfo InputDetail { get; }
/// <summary>
/// 输出类型,现在只支持 LogService。
/// </summary>
public String OutputType { get; }
/// <summary>
/// 输出详情。
/// </summary>
public ConfigOutputDetailInfo OutputDetail { get; }
/// <summary>
/// Logtail 配置日志样例,最大支持 1000 字节。
/// </summary>
public String LogSample { get; set; }
public CreateConfigRequest(String configName, String inputType, ConfigInputDetailInfo inputDetail, String outputType, ConfigOutputDetailInfo outputDetail)
{
this.ConfigName = configName;
this.InputType = inputType;
this.InputDetail = inputDetail;
this.OutputType = outputType;
this.OutputDetail = outputDetail;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// DeleteConfigRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Config
{
public class DeleteConfigRequest : ProjectScopedRequest
{
/// <summary>
/// 日志配置名称。
/// </summary>
public String ConfigName { get; }
public DeleteConfigRequest(String configName)
{
this.ConfigName = configName;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// GetAppliedMachineGroupsRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Config
{
public class GetAppliedMachineGroupsRequest : ProjectScopedRequest
{
/// <summary>
/// 日志配置名称。
/// </summary>
public String ConfigName { get; }
public GetAppliedMachineGroupsRequest(String configName)
{
this.ConfigName = configName;
}
}
}

View File

@@ -0,0 +1,50 @@
//
// GetAppliedMachineGroupsResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.Config
{
public class GetAppliedMachineGroupsResult
{
/// <summary>
/// 返回的 machineGroup 数目。
/// </summary>
public Int32 Count { get; }
/// <summary>
/// 返回的 machineGroup 名称列表。
/// </summary>
public IList<String> MachineGroups { get; }
public GetAppliedMachineGroupsResult(Int32 count, IList<String> machineGroups)
{
this.Count = count;
this.MachineGroups = machineGroups;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// GetConfigRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Config
{
public class GetConfigRequest : ProjectScopedRequest
{
/// <summary>
/// 日志配置名称。
/// </summary>
public String ConfigName { get; }
public GetConfigRequest(String configName)
{
this.ConfigName = configName;
}
}
}

View File

@@ -0,0 +1,93 @@
//
// GetConfigResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.Config
{
public class GetConfigResult
{
/// <summary>
/// 日志配置名称, Project 下唯一。
/// </summary>
public String ConfigName { get; }
/// <summary>
/// 输入类型,现在只支持 file。
/// </summary>
public String InputType { get; }
/// <summary>
/// 输入详情。
/// </summary>
public ConfigInputDetailInfo InputDetail { get; }
/// <summary>
/// 输出类型,现在只支持 LogService。
/// </summary>
public String OutputType { get; }
/// <summary>
/// 输出详情。
/// </summary>
public ConfigOutputDetailExtInfo OutputDetail { get; }
/// <summary>
/// 配置创建时间。
/// </summary>
public Int32 CreateTime { get; }
/// <summary>
/// 该资源服务端更新时间。
/// </summary>
public Int32 LastModifyTime { get; }
public GetConfigResult(String configName, String inputType, ConfigInputDetailInfo inputDetail, String outputType, ConfigOutputDetailExtInfo outputDetail, Int32 createTime, Int32 lastModifyTime)
{
this.ConfigName = configName;
this.InputType = inputType;
this.InputDetail = inputDetail;
this.OutputType = outputType;
this.OutputDetail = outputDetail;
this.CreateTime = createTime;
this.LastModifyTime = lastModifyTime;
}
public class ConfigOutputDetailExtInfo : ConfigOutputDetailInfo
{
/// <summary>
/// Project 所在的访问地址。
/// </summary>
public String Endpoint { get; }
public ConfigOutputDetailExtInfo(String logstoreName, String endpoint)
: base(logstoreName)
{
this.Endpoint = endpoint;
}
}
}
}

View File

@@ -0,0 +1,47 @@
//
// ListConfigRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Config
{
public class ListConfigRequest : ProjectScopedRequest
{
public const Int32 DefaultOffset = 0;
public const Int32 DefaultSize = 500;
/// <summary>
/// 返回记录的起始位置,默认为 0。
/// </summary>
public Int32 Offset { get; set; } = DefaultOffset;
/// <summary>
/// 每页返回最大条目,默认 500最大值
/// </summary>
public Int32 Size { get; set; } = DefaultSize;
}
}

View File

@@ -0,0 +1,56 @@
//
// ListConfigResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.Config
{
public class ListConfigResult
{
/// <summary>
/// 返回的 config 数目。
/// </summary>
public Int32 Count { get; }
/// <summary>
/// 在服务端 config 总数。
/// </summary>
public Int32 Total { get; }
/// <summary>
/// 返回的 config 名称列表。
/// </summary>
public IList<String> Configs { get; }
public ListConfigResult(Int32 count, Int32 total, IList<String> configs)
{
this.Count = count;
this.Total = total;
this.Configs = configs;
}
}
}

View File

@@ -0,0 +1,68 @@
//
// UpdateConfigRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Config
{
public class UpdateConfigRequest : ProjectScopedRequest
{
/// <summary>
/// 日志配置名称, Project 下唯一。
/// </summary>
public String ConfigName { get; }
/// <summary>
/// 输入类型,现在只支持 file。
/// </summary>
public String InputType { get; }
/// <summary>
/// 输入详情。
/// </summary>
public ConfigInputDetailInfo InputDetail { get; }
/// <summary>
/// 输出类型,现在只支持 LogService。
/// </summary>
public String OutputType { get; }
/// <summary>
/// 输出详情。
/// </summary>
public ConfigOutputDetailInfo OutputDetail { get; }
public UpdateConfigRequest(String configName, String inputType, ConfigInputDetailInfo inputDetail, String outputType, ConfigOutputDetailInfo outputDetail)
{
this.ConfigName = configName;
this.InputType = inputType;
this.InputDetail = inputDetail;
this.OutputType = outputType;
this.OutputDetail = outputDetail;
}
}
}

View File

@@ -0,0 +1,66 @@
//
// GetLogHistogramsRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Log
{
public class GetLogHistogramsRequest : ProjectScopedRequest
{
/// <summary>
/// 需要查询日志的 Logstore 名称。
/// </summary>
public String Logstorename { get; }
/// <summary>
/// 查询开始时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。
/// </summary>
public Int32 From { get; }
/// <summary>
/// 查询结束时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。
/// </summary>
public Int32 To { get; }
/// <summary>
/// 查询日志主题。
/// </summary>
public String Topic { get; set; }
/// <summary>
/// 查询表达式。关于查询表达式的详细语法,请参考 查询语法。
/// </summary>
public String Query { get; set; }
public GetLogHistogramsRequest(String logstorename, Int32 from, Int32 to)
{
this.Logstorename = logstorename;
this.From = from;
this.To = to;
}
}
}

View File

@@ -0,0 +1,54 @@
//
// GetLogHistogramsResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.Log
{
public class GetLogHistogramsResult
{
/// <summary>
/// 查询结果的状态。可以有 Incomplete 和 Complete 两个选值,表示结果是否完整。
/// </summary>
public LogProgressState Progress { get; set; }
/// <summary>
/// 当前查询结果中所有日志总数。
/// </summary>
public Int32 Count { get; set; }
/// <summary>
/// 当前查询结果在划分的子时间区间上的分布状况,具体结构见下面的描述。
/// </summary>
public IList<LogHistogramInfo> Histograms { get; }
public GetLogHistogramsResult(IList<LogHistogramInfo> histograms)
{
this.Histograms = histograms;
}
}
}

View File

@@ -0,0 +1,85 @@
//
// GetLogsRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Log
{
public class GetLogsRequest : ProjectScopedRequest
{
public const Int32 DefaultLine = 100;
public const Int32 DefaultOffset = 0;
public const Boolean DefaultReverse = false;
/// <summary>
/// 需要查询日志的 Logstore 名称。
/// </summary>
public String Logstorename { get; }
/// <summary>
/// 查询开始时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。
/// </summary>
public Int32 From { get; }
/// <summary>
/// 查询结束时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。
/// </summary>
public Int32 To { get; }
/// <summary>
/// 查询日志主题。
/// </summary>
public String Topic { get; set; }
/// <summary>
/// 查询表达式。关于查询表达式的详细语法,请参考 查询语法。
/// </summary>
public String Query { get; set; }
/// <summary>
/// 请求返回的最大日志条数。取值范围为 0~100默认值为 100。
/// </summary>
public Int32 Line { get; set; }
/// <summary>
/// 请求返回日志的起始点。取值范围为 0 或正整数,默认值为 0。
/// </summary>
public Int32 Offset { get; set; }
/// <summary>
/// 是否按日志时间戳逆序返回日志。true 表示逆序false 表示顺序,默认值为 false。
/// </summary>
public Boolean Reverse { get; set; }
public GetLogsRequest(String logstorename, Int32 from, Int32 to)
{
this.Logstorename = logstorename;
this.From = from;
this.To = to;
}
}
}

View File

@@ -0,0 +1,84 @@
//
// GetLogsResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.Log
{
public class GetLogsResult
{
/// <summary>
/// 查询结果的状态。可以有 Incomplete 和 Complete 两个选值,表示本次是否完整。
/// </summary>
public LogProgressState Progress { get; set; }
/// <summary>
/// 当前查询结果返回的日志总数(非总数)。
/// </summary>
public Int32 Count { get; set; }
/// <summary>
///
/// </summary>
public Int32 ProcessedRows { get; set; }
/// <summary>
///
/// </summary>
public Int32 ElapsedMillisecond { get; set; }
/// <summary>
///
/// </summary>
public Boolean HasSql { get; set; }
/// <summary>
///
/// </summary>
public String AggQuery { get; set; }
/// <summary>
///
/// </summary>
public String WhereQuery { get; set; }
/// <summary>
///
/// </summary>
public LogQueryInfo QueryInfo { get; set; }
/// <summary>
/// 日志内容。
/// </summary>
public IList<IDictionary<String, String>> Logs { get; }
public GetLogsResult(IList<IDictionary<String, String>> logs)
{
this.Logs = logs;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// GetProjectLogsRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Log
{
public class GetProjectLogsRequest : ProjectScopedRequest
{
/// <summary>
/// 查询sql条件。
/// </summary>
public String Query { get; }
public GetProjectLogsRequest(String query)
{
this.Query = query;
}
}
}

View File

@@ -0,0 +1,48 @@
//
// LogGroupInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.Log
{
public class LogGroupInfo
{
public String Topic { get; set; }
public String Source { get; set; }
public IDictionary<String, String> LogTags { get; set; }
public IList<LogInfo> Logs { get; set; }
public LogGroupInfo()
{
this.LogTags = new Dictionary<String, String>();
this.Logs = new List<LogInfo>();
}
}
}

View File

@@ -0,0 +1,61 @@
//
// LogHistogramInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.Log
{
public class LogHistogramInfo
{
/// <summary>
/// 子时间区间的开始时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。
/// </summary>
public Int32 From { get; }
/// <summary>
/// 子时间区间的结束时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。
/// </summary>
public Int32 To { get; }
/// <summary>
/// 当前查询结果在该子时间区间内命中的日志条数。
/// </summary>
public Int32 Count { get; }
/// <summary>
/// 当前查询结果在该子时间区间内的结果是否完整,可以有 Incomplete 和 Complete 两个选值。
/// </summary>
public LogProgressState Progress { get; }
public LogHistogramInfo(Int32 from, Int32 to, Int32 count, LogProgressState progress)
{
this.From = from;
this.To = to;
this.Count = count;
this.Progress = progress;
}
}
}

View File

@@ -0,0 +1,64 @@
//
// LogInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using Aliyun.Api.LogService.Utils;
namespace Aliyun.Api.LogService.Domain.Log
{
public class LogInfo
{
public static IEnumerable<String> InvalidContentKeys { get; } = new HashSet<String>
{
"__time__",
"__source__",
"__topic__",
"__partition_time__",
"_extract_others_",
"__extract_others__"
};
public DateTimeOffset Time { get; set; } = DateTime.Now;
public IDictionary<String, String> Contents { get; set; }
public LogInfo()
{
this.Contents = new Dictionary<String, String>();
}
public void Validate()
{
var invalidKeys = this.Contents.Keys.Intersect(InvalidContentKeys).ToArray();
if (invalidKeys.IsNotEmpty())
{
throw new ArgumentException($"{nameof(this.Contents)} contains forbidden keys: {String.Join(", ", invalidKeys)}.");
}
}
}
}

View File

@@ -0,0 +1,44 @@
//
// LogProgressState.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Domain.Log
{
/**
* 查询结果状态。
*/
public enum LogProgressState
{
/**
* 本次查询返回的结果是完整的结果。
*/
Complete,
/**
* 本次查询返回的结果只是部分结果。
*/
Incomplete
}
}

View File

@@ -0,0 +1,50 @@
//
// LogQueryInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.Log
{
public class LogQueryInfo
{
/// <summary>
///
/// </summary>
public IList<String> Keys { get; }
/// <summary>
///
/// </summary>
public IList<IList<String>> Terms { get; }
public LogQueryInfo(IList<String> keys, IList<IList<String>> terms)
{
this.Keys = keys;
this.Terms = terms;
}
}
}

View File

@@ -0,0 +1,55 @@
//
// PostLogsRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Log
{
public class PostLogsRequest : ProjectScopedRequest
{
/// <summary>
/// 日志库名称。
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// 一组日志。
/// </summary>
public LogGroupInfo LogGroup { get; }
/// <summary>
///(可选)标记日志应该路由到哪个 shard 的标记。
/// </summary>
public String HashKey { get; set; }
public PostLogsRequest(String logstoreName, LogGroupInfo logGroup)
{
this.LogstoreName = logstoreName;
this.LogGroup = logGroup;
}
}
}

View File

@@ -0,0 +1,62 @@
//
// PullLogsRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.Log
{
public class PullLogsRequest : ProjectScopedRequest
{
/// <summary>
/// 日志库名称
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// Shard ID
/// </summary>
public Int32 ShardId { get; }
/// <summary>
/// 游标,用以表示从什么位置开始读取数据,相当于起点。
/// </summary>
public String Cursor { get; }
/// <summary>
/// 返回的 loggroup 数目,范围为 0~1000。
/// </summary>
public Int32 Count { get; }
public PullLogsRequest(String logstoreName, Int32 shardId, String cursor, Int32 count)
{
this.LogstoreName = logstoreName;
this.ShardId = shardId;
this.Cursor = cursor;
this.Count = count;
}
}
}

View File

@@ -0,0 +1,40 @@
//
// PullLogsResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.Log
{
public class PullLogsResult
{
public IList<LogGroupInfo> LogGroups { get; }
public PullLogsResult(IList<LogGroupInfo> logGroups)
{
this.LogGroups = logGroups;
}
}
}

View File

@@ -0,0 +1,89 @@
//
// LogServiceClientBuilders.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Infrastructure.Protocol;
namespace Aliyun.Api.LogService.Domain
{
/// <summary>
/// 日志服务业务异常。
/// </summary>
public class LogServiceException : Exception
{
/// <summary>
/// 服务端产生的标示该请求的唯一 ID。
/// 该响应头与具体应用无关,主要用于跟踪和调查问题。
/// 如果用户希望调查出现问题的 API 请求,可以向 Log Service 团队提供该 ID。
/// </summary>
public String RequestId { get; }
/// <summary>
/// 对应的错误码。
/// </summary>
public ErrorCode ErrorCode { get; }
/// <summary>
/// 对应的错误消息。
/// </summary>
public String ErrorMessage { get; }
public LogServiceException(String requestId, ErrorCode errorCode)
: base(FormatMessage(requestId, errorCode))
{
this.RequestId = requestId;
this.ErrorCode = errorCode;
this.ErrorMessage = null;
}
public LogServiceException(String requestId, ErrorCode errorCode, String errorMessage)
: base(FormatMessage(requestId, errorCode, errorMessage))
{
this.RequestId = requestId;
this.ErrorCode = errorCode;
this.ErrorMessage = errorMessage;
}
public LogServiceException(String requestId, ErrorCode errorCode, Exception innerException)
: base(FormatMessage(requestId, errorCode), innerException)
{
this.RequestId = requestId;
this.ErrorCode = errorCode;
this.ErrorMessage = null;
}
public LogServiceException(String requestId, ErrorCode errorCode, String errorMessage, Exception innerException)
: base(FormatMessage(requestId, errorCode), innerException)
{
this.RequestId = requestId;
this.ErrorCode = errorCode;
this.ErrorMessage = errorMessage;
}
private static String FormatMessage(String requestId, ErrorCode errorCode, String errorMessage = null)
=> $"[{requestId}] {errorCode}{(errorMessage == null ? String.Empty : $" ({errorMessage})")}";
}
}

View File

@@ -0,0 +1,56 @@
//
// CreateLogStoreRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore
{
public class CreateLogStoreRequest : ProjectScopedRequest
{
/// <summary>
/// Logstore 的名称,在 Project 下必须唯一。
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// 数据的保存时间单位为天范围1~365额外需求请提交工单
/// </summary>
public Int32 Ttl { get; }
/// <summary>
/// 该 Logstore 的 Shard 数量,单位为个,范围为 1~10。
/// </summary>
public Int32 ShardCount { get; }
public CreateLogStoreRequest(String logstoreName, Int32 ttl, Int32 shardCount)
{
this.LogstoreName = logstoreName;
this.Ttl = ttl;
this.ShardCount = shardCount;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// DeleteLogStoreRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore
{
public class DeleteLogStoreRequest : ProjectScopedRequest
{
/// <summary>
/// Logstore 的名称,在 Project 下必须唯一。
/// </summary>
public String LogstoreName { get; }
public DeleteLogStoreRequest(String logstoreName)
{
this.LogstoreName = logstoreName;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// GetLogStoreRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore
{
public class GetLogStoreRequest : ProjectScopedRequest
{
/// <summary>
/// Logstore 的名称,在 Project 下必须唯一。
/// </summary>
public String LogstoreName { get; }
public GetLogStoreRequest(String logstoreName)
{
this.LogstoreName = logstoreName;
}
}
}

View File

@@ -0,0 +1,67 @@
//
// GetLogStoreResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.LogStore
{
public class GetLogStoreResult
{
///<summary>
/// logstore 的名称, 在该 project 下唯一。
///</summary>
public String LogstoreName { get; }
///<summary>
/// 日志数据生命周期TTL单位为天最小为 1 天。
///</summary>
public Int32 Ttl { get; }
///<summary>
/// 日志数据 服务单元。
///</summary>
public Int32 ShardCount { get; }
///<summary>
/// 该资源服务端创建时间。
///</summary>
public Int32 CreateTime { get; }
///<summary>
/// 该资源服务端更新时间。
///</summary>
public Int32 LastModifyTime { get; }
public GetLogStoreResult(String logstoreName, Int32 ttl, Int32 shardCount, Int32 createTime, Int32 lastModifyTime)
{
this.LogstoreName = logstoreName;
this.Ttl = ttl;
this.ShardCount = shardCount;
this.CreateTime = createTime;
this.LastModifyTime = lastModifyTime;
}
}
}

View File

@@ -0,0 +1,69 @@
//
// CreateIndexRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using Aliyun.Api.LogService.Domain.Project;
using Newtonsoft.Json;
namespace Aliyun.Api.LogService.Domain.LogStore.Index
{
public class CreateIndexRequest : ProjectScopedRequest
{
/// <summary>
/// Logstore 的名称,在 Project 下必须唯一。
/// </summary>
[JsonIgnore]
public String LogstoreName { get; }
/// <summary>
/// 全文索引对于日志中value的索引属性全文索引和字段查询必须至少配置一类。
/// </summary>
public IndexLineInfo Line { get; }
/// <summary>
/// 字段查询对于具体字段的value索引属性全文索引和字段查询必须至少配置一类。
/// </summary>
public IDictionary<String, IndexKeyInfo> Keys { get; }
public CreateIndexRequest(String logstoreName, IndexLineInfo line) : this(logstoreName, line, null)
{
// Delegate constructor.
}
public CreateIndexRequest(String logstoreName, IDictionary<String, IndexKeyInfo> keys) : this(logstoreName, null, keys)
{
// Delegate constructor.
}
public CreateIndexRequest(String logstoreName, IndexLineInfo line, IDictionary<String, IndexKeyInfo> keys)
{
this.Line = line;
this.Keys = keys;
this.LogstoreName = logstoreName;
}
}
}

View File

@@ -0,0 +1,139 @@
//
// IndexKeyInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using Aliyun.Api.LogService.Utils;
using Newtonsoft.Json;
namespace Aliyun.Api.LogService.Domain.LogStore.Index
{
/*****************************************
* TODO: Remove the coupling of Json.NET *
*****************************************/
public class IndexKeyInfo
{
/// <summary>
/// 字段类型目前支持textlongdouble和json等四种。
/// </summary>
public String Type { get; }
/// <summary>
/// 是否支持统计分析默认值为false标识不支持。
/// </summary>
[JsonProperty("doc_value")]
public Boolean? DocValue { get; set; }
/// <summary>
/// 查询别名,默认为空。
/// </summary>
public String Alias { get; set; }
public IndexKeyInfo(String type)
{
this.Type = type;
}
}
public class IndexTextKeyInfo : IndexKeyInfo
{
/// <summary>
/// 是否区分大小写默认值为false表示不区分。
/// </summary>
public Boolean? CaseSensitive { get; set; }
/// <summary>
/// 分词字符列表,只支持单个英文字符。
/// </summary>
public IEnumerable<Char> Token { get; }
/// <summary>
/// 是否进行中文分词默认值为false表示不进行中文分词。
/// </summary>
public Boolean? Chn { get; set; }
public IndexTextKeyInfo(IEnumerable<Char> token)
: base("text")
{
this.Token = token.Freeze();
}
}
public class IndexLongKeyInfo : IndexKeyInfo
{
public IndexLongKeyInfo() : base("long")
{
// Empty constructor.
}
}
public class IndexDoubleKeyInfo : IndexKeyInfo
{
public IndexDoubleKeyInfo() : base("double")
{
// Empty constructor.
}
}
public class IndexJsonKeyInfo : IndexKeyInfo
{
/// <summary>
/// 分词字符列表,只支持单个英文字符。
/// </summary>
public IEnumerable<Char> Token { get; }
/// <summary>
/// 是否进行中文分词默认值为false表示不进行中文分词。
/// </summary>
public Boolean? Chn { get; set; }
/// <summary>
/// 是否对所有json key进行索引默认为否。
/// </summary>
[JsonProperty("index_all")]
public Boolean? IndexAll { get; set; }
/// <summary>
/// 表示解析json的最大深度。
/// </summary>
[JsonProperty("max_depth")]
public Int32 MaxDepth { get; }
/// <summary>
/// 表示json中具体key的索引属性。 其中object中每个item支持textlong和double三种类型属性对应类型一致。
/// </summary>
[JsonProperty("json_keys")]
public IDictionary<String, IndexKeyInfo> JsonKeys { get; set; }
public IndexJsonKeyInfo(IEnumerable<Char> token, Int32 maxDepth)
: base("json")
{
this.Token = token.Freeze();
this.MaxDepth = maxDepth;
}
}
}

View File

@@ -0,0 +1,141 @@
//
// IndexKeysBuilder.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using Aliyun.Api.LogService.Utils;
namespace Aliyun.Api.LogService.Domain.LogStore.Index
{
public class IndexKeysBuilder
{
private readonly Boolean allowJson;
private readonly IDictionary<String, IndexKeyInfo> keys = new Dictionary<String, IndexKeyInfo>();
public IndexKeysBuilder() : this(true)
{
// Empty constructor.
}
private IndexKeysBuilder(Boolean allowJson)
{
this.allowJson = allowJson;
}
public IndexKeysBuilder AddText(String key, params Char[] token)
{
return this.AddText(key, token.AsEnumerable());
}
public IndexKeysBuilder AddText(String key, IEnumerable<Char> token, Boolean? caseSensitive = null, Boolean? chn = null)
{
var frozenToken = token?.ToArray(); // Avoid recalculate the non-reentranceable IEnumerable.
Ensure.NotEmpty(frozenToken, nameof(token));
var textKeyInfo = new IndexTextKeyInfo(frozenToken)
{
CaseSensitive = caseSensitive,
Chn = chn
};
this.keys.Add(key, textKeyInfo);
return this;
}
public IndexKeysBuilder AddLong(String key, Boolean? docValue = null, String alias = null)
{
var longKeyInfo = new IndexLongKeyInfo
{
DocValue = docValue,
Alias = alias
};
this.keys.Add(key, longKeyInfo);
return this;
}
public IndexKeysBuilder AddDouble(String key, Boolean? docValue = null, String alias = null)
{
var doubleKeyInfo = new IndexDoubleKeyInfo
{
DocValue = docValue,
Alias = alias
};
this.keys.Add(key, doubleKeyInfo);
return this;
}
public IndexKeysBuilder AddJson(String key, Int32 maxDepth, params Char[] token)
{
return this.AddJson(key, token, maxDepth);
}
public IndexKeysBuilder AddJson(String key, IEnumerable<Char> token, Int32 maxDepth,
Boolean? chn = null, Boolean? indexAll = null, Action<IndexKeysBuilder> jsonKeys = null)
{
if (!this.allowJson)
{
throw new InvalidOperationException("json index info is not support in current state.");
}
var frozenToken = token?.ToArray(); // Avoid recalculate the non-reentranceable IEnumerable.
Ensure.NotEmpty(frozenToken, nameof(token));
IDictionary<String, IndexKeyInfo> subKeys;
if (jsonKeys != null)
{
var subBuilder = new IndexKeysBuilder(false);
jsonKeys(subBuilder);
subKeys = subBuilder.Build();
} else
{
subKeys = null;
}
var jsonKeyInfo = new IndexJsonKeyInfo(frozenToken, maxDepth)
{
Chn = chn,
IndexAll = indexAll,
JsonKeys = subKeys
};
this.keys.Add(key, jsonKeyInfo);
return this;
}
public IDictionary<String, IndexKeyInfo> Build()
{
return new Dictionary<String, IndexKeyInfo>(this.keys);
}
}
}

View File

@@ -0,0 +1,55 @@
//
// IndexLineInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using Aliyun.Api.LogService.Utils;
namespace Aliyun.Api.LogService.Domain.LogStore.Index
{
public class IndexLineInfo
{
/// <summary>
/// 是否区分大小写默认值为false表示不区分。
/// </summary>
public Boolean? CaseSensitive { get; set; }
/// <summary>
/// 分词字符列表,只支持单个英文字符。
/// </summary>
public IEnumerable<Char> Token { get; }
/// <summary>
/// 是否进行中文分词默认值为false表示不进行中文分词。
/// </summary>
public Boolean? Chn { get; set; }
public IndexLineInfo(IEnumerable<Char> token)
{
this.Token = token.Freeze();
}
}
}

View File

@@ -0,0 +1,52 @@
//
// ListLogStoreRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore
{
public class ListLogStoreRequest : ProjectScopedRequest
{
internal const Int32 DefaultOffset = 1;
internal const Int32 DefaultSize = 500;
/// <summary>
/// 用于请求的 Logstore 名称(支持部分匹配)。
/// </summary>
public String LogstoreName { get; set; }
/// <summary>
/// 返回记录的起始位置,默认值为 1。
/// </summary>
public Int32 Offset { get; set; } = DefaultOffset;
/// <summary>
/// 每页返回最大条目,默认 500最大值
/// </summary>
public Int32 Size { get; set; } = DefaultSize;
}
}

View File

@@ -0,0 +1,56 @@
//
// ListLogStoreResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.LogStore
{
public class ListLogStoreResult
{
///<summary>
/// 返回的 Logstore 数目。
///</summary>
public Int32 Count { get; }
///<summary>
/// Logstore 总数。
///</summary>
public Int32 Total { get; }
///<summary>
/// 返回的 Logstore 名称列表。
///</summary>
public IList<String> Logstores { get; }
public ListLogStoreResult(Int32 count, Int32 total, IList<String> logstores)
{
this.Count = count;
this.Total = total;
this.Logstores = logstores;
}
}
}

View File

@@ -0,0 +1,56 @@
//
// GetCursorRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore.Shard
{
public class GetCursorRequest : ProjectScopedRequest
{
/// <summary>
/// 日志库名称
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// Shard ID
/// </summary>
public Int32 ShardId { get; }
/// <summary>
/// 时间点UNIX下秒数或 beginend
/// </summary>
public String From { get; }
public GetCursorRequest(String logstoreName, Int32 shardId, String from)
{
this.LogstoreName = logstoreName;
this.ShardId = shardId;
this.From = from;
}
}
}

View File

@@ -0,0 +1,43 @@
//
// GetCursorResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.LogStore.Shard
{
public class GetCursorResult
{
/// <summary>
/// 游标
/// </summary>
public String Cursor { get; }
public GetCursorResult(String cursor)
{
this.Cursor = cursor;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// ListShardRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore.Shard
{
public class ListShardRequest : ProjectScopedRequest
{
/// <summary>
/// 日志库名称
/// </summary>
public String LogstoreName { get; }
public ListShardRequest(String logstoreName)
{
this.LogstoreName = logstoreName;
}
}
}

View File

@@ -0,0 +1,50 @@
//
// MergeShardRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore.Shard
{
public class MergeShardRequest : ProjectScopedRequest
{
/// <summary>
/// 日志库名称
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// Shard ID
/// </summary>
public Int32 ShardId { get; }
public MergeShardRequest(String logstoreName, Int32 shardId)
{
this.LogstoreName = logstoreName;
this.ShardId = shardId;
}
}
}

View File

@@ -0,0 +1,71 @@
//
// ShardInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.LogStore.Shard
{
public class ShardInfo
{
/// <summary>
/// Shard ID分区号。
/// </summary>
public Int32 ShardId { get; }
/// <summary>
/// 分区的状态。
/// <list type="bullet">
/// <item><description>readwrite可以读写</description></item>
/// <item><description>readonly只读数据</description></item>
/// </list>
/// </summary>
public ShardState Status { get; }
/// <summary>
/// 分区起始的Key值分区范围中包含该Key值。
/// </summary>
public String InclusiveBeginKey { get; }
/// <summary>
/// 分区结束的Key值分区范围中不包含该Key值。
/// </summary>
public String ExclusiveEndKey { get; }
/// <summary>
/// 分区创建时间。
/// </summary>
public Int64 CreateTime { get; }
public ShardInfo(Int32 shardId, ShardState status, String inclusiveBeginKey, String exclusiveEndKey, Int64 createTime)
{
this.ShardId = shardId;
this.Status = status;
this.InclusiveBeginKey = inclusiveBeginKey;
this.ExclusiveEndKey = exclusiveEndKey;
this.CreateTime = createTime;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// ShardState.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Domain.LogStore.Shard
{
/// <summary>
/// 分区状态。
/// </summary>
public enum ShardState
{
/// <summary>
/// 只读。
/// </summary>
ReadOnly,
/// <summary>
/// 可以读写。
/// </summary>
ReadWrite,
}
}

View File

@@ -0,0 +1,56 @@
//
// SplitShardRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore.Shard
{
public class SplitShardRequest : ProjectScopedRequest
{
/// <summary>
/// 日志库名称
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// Shard ID
/// </summary>
public Int32 ShardId { get; }
/// <summary>
/// split 切分位置
/// </summary>
public String SplitKey { get; }
public SplitShardRequest(String logstoreName, Int32 shardId, String splitKey)
{
this.LogstoreName = logstoreName;
this.ShardId = shardId;
this.SplitKey = splitKey;
}
}
}

View File

@@ -0,0 +1,81 @@
//
// GetShipperRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore.Shipper
{
public class GetShipperRequest : ProjectScopedRequest
{
public const Int32 DefaultOffset = 0;
public const Int32 DefaultSize = 100;
/// <summary>
/// 日志库名称,同一 Project 下唯一。
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// 日志投递规则名称,同一 Logstore 下唯一。
/// </summary>
public String ShipperName { get; }
/// <summary>
/// 日志投递任务创建时间区间。
/// </summary>
public Int32 From { get; }
/// <summary>
/// 日志投递任务创建时间区间。
/// </summary>
public Int32 To { get; }
/// <summary>
/// 默认为空,表示返回所有状态的任务,目前支持 success/fail/running 等状态。
/// </summary>
public String Status { get; set; }
/// <summary>
/// 返回指定时间区间内投递任务的起始数目,默认值为 0。
/// </summary>
public Int32 Offset { get; set; } = DefaultOffset;
/// <summary>
/// 返回指定时间区间内投递任务的数目,默认值为 100最大为 500。
/// </summary>
public Int32 Size { get; set; } = DefaultSize;
public GetShipperRequest(String logstoreName, String shipperName, Int32 from, Int32 to)
{
this.LogstoreName = logstoreName;
this.ShipperName = shipperName;
this.From = from;
this.To = to;
}
}
}

View File

@@ -0,0 +1,130 @@
//
// GetShipperResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.LogStore.Shipper
{
public class GetShipperResult
{
/// <summary>
/// 返回的任务个数。
/// </summary>
public Int32 Count { get; }
/// <summary>
/// 指定范围内任务总数。
/// </summary>
public Int32 Total { get; }
/// <summary>
/// 指定范围内任务汇总状态,具体请参考下表。
/// </summary>
public StatisticsResult Statistics { get; }
/// <summary>
/// 指定范围内投递任务具体详情,具体请参考下表。
/// </summary>
public IList<TasksResult> Tasks { get; }
public GetShipperResult(Int32 count, Int32 total, StatisticsResult statistics, IList<TasksResult> tasks)
{
this.Count = count;
this.Total = total;
this.Statistics = statistics;
this.Tasks = tasks;
}
public class StatisticsResult
{
/// <summary>
/// 指定范围内状态为 running 的任务个数。
/// </summary>
public Int32 Running { get; }
/// <summary>
/// 指定范围内状态为 success 的任务个数。
/// </summary>
public Int32 Success { get; }
/// <summary>
/// 指定范围内状态为 fail 的任务个数。
/// </summary>
public Int32 Fail { get; }
public StatisticsResult(Int32 running, Int32 success, Int32 fail)
{
this.Running = running;
this.Success = success;
this.Fail = fail;
}
}
public class TasksResult
{
/// <summary>
/// 具体投递任务的任务唯一 ID。
/// </summary>
public String Id { get; }
/// <summary>
/// 投递任务的具体状态,可能为 running/success/fail 中的一种。
/// </summary>
public String TaskStatus { get; }
/// <summary>
/// 投递任务失败时的具体错误信息。
/// </summary>
public String TaskMessage { get; }
/// <summary>
/// 投递任务创建时间。
/// </summary>
public Int32 TaskCreateTime { get; }
/// <summary>
/// 投递任务中的最近一条日志到达服务端时间(非日志时间,是服务端接收时间)。
/// </summary>
public Int32 TaskLastDataReceiveTime { get; }
/// <summary>
/// 投递任务结束时间。
/// </summary>
public Int32 TaskFinishTime { get; }
public TasksResult(String id, String taskStatus, String taskMessage, Int32 taskCreateTime, Int32 taskLastDataReceiveTime, Int32 taskFinishTime)
{
this.Id = id;
this.TaskStatus = taskStatus;
this.TaskMessage = taskMessage;
this.TaskCreateTime = taskCreateTime;
this.TaskLastDataReceiveTime = taskLastDataReceiveTime;
this.TaskFinishTime = taskFinishTime;
}
}
}
}

View File

@@ -0,0 +1,57 @@
//
// RetryShipperRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore.Shipper
{
public class RetryShipperRequest : ProjectScopedRequest
{
/// <summary>
/// 日志库名称,同一 Project 下唯一。
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// 日志投递规则名称,同一 Logstore 下唯一。
/// </summary>
public String ShipperName { get; }
/// <summary>
/// 需要重试的任务ID。
/// </summary>
public IEnumerable<String> TaskIds { get; }
public RetryShipperRequest(String logstoreName, String shipperName, IEnumerable<String> taskIds)
{
this.LogstoreName = logstoreName;
this.ShipperName = shipperName;
this.TaskIds = taskIds;
}
}
}

View File

@@ -0,0 +1,56 @@
//
// UpdateLogStoreRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.LogStore
{
public class UpdateLogStoreRequest : ProjectScopedRequest
{
/// <summary>
/// Logstore 的名称,在 Project 下必须唯一。
/// </summary>
public String LogstoreName { get; }
/// <summary>
/// 数据的保存时间单位为天范围1~365额外需求请提交工单
/// </summary>
public Int32 Ttl { get; }
/// <summary>
/// 该 Logstore 的 Shard 数量,单位为个,范围为 1~10。
/// </summary>
public Int32 ShardCount { get; }
public UpdateLogStoreRequest(String logstoreName, Int32 ttl, Int32 shardCount)
{
this.LogstoreName = logstoreName;
this.Ttl = ttl;
this.ShardCount = shardCount;
}
}
}

View File

@@ -0,0 +1,50 @@
//
// ApplyConfigToMachineGroupRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class ApplyConfigToMachineGroupRequest : ProjectScopedRequest
{
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
/// <summary>
/// 日志配置名称。
/// </summary>
public String ConfigName { get; }
public ApplyConfigToMachineGroupRequest(String groupName, String configName)
{
this.GroupName = groupName;
this.ConfigName = configName;
}
}
}

View File

@@ -0,0 +1,67 @@
//
// CreateMachineGroupRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class CreateMachineGroupRequest : ProjectScopedRequest
{
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
/// <summary>
/// 机器分组类型,默认为空。
/// </summary>
public String GroupType { get; set; }
/// <summary>
/// 机器标识类型,分为 IP 和 userdefined 两种。
/// </summary>
public String MachineIdentifyType { get; }
/// <summary>
/// 机器分组的属性,默认为空。
/// </summary>
public MachineGroupAttributeInfo GroupAttribute { get; set; }
/// <summary>
/// 具体的机器标识,可以是 IP 或 userdefined-id。
/// </summary>
public IEnumerable<String> MachineList { get; }
public CreateMachineGroupRequest(String groupName, String machineIdentifyType, IEnumerable<String> machineList)
{
this.GroupName = groupName;
this.MachineIdentifyType = machineIdentifyType;
this.MachineList = machineList;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// DeleteMachineGroupRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class DeleteMachineGroupRequest : ProjectScopedRequest
{
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
public DeleteMachineGroupRequest(String groupName)
{
this.GroupName = groupName;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// GetAppliedConfigsRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class GetAppliedConfigsRequest : ProjectScopedRequest
{
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
public GetAppliedConfigsRequest(String groupName)
{
this.GroupName = groupName;
}
}
}

View File

@@ -0,0 +1,50 @@
//
// GetAppliedConfigsResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class GetAppliedConfigsResult
{
/// <summary>
/// 返回的 config 数目。
/// </summary>
public Int32 Count { get; }
/// <summary>
/// 返回的 config 名称列表。
/// </summary>
public IList<String> Configs { get; }
public GetAppliedConfigsResult(Int32 count, IList<String> configs)
{
this.Count = count;
this.Configs = configs;
}
}
}

View File

@@ -0,0 +1,44 @@
//
// GetMachineGroupRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class GetMachineGroupRequest : ProjectScopedRequest
{
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
public GetMachineGroupRequest(String groupName)
{
this.GroupName = groupName;
}
}
}

View File

@@ -0,0 +1,81 @@
//
// GetMachineGroupResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class GetMachineGroupResult
{
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
/// <summary>
/// 机器分组类型,默认为空。
/// </summary>
public String GroupType { get; set; }
/// <summary>
/// 机器分组的属性,默认为空。
/// </summary>
public MachineGroupAttributeInfo GroupAttribute { get; }
/// <summary>
/// 机器标识类型,分为 IP 和 userdefined 两种。
/// </summary>
public String MachineIdentifyType { get; }
/// <summary>
/// 具体的机器标识,可以是 IP 或 userdefined-id。
/// </summary>
public IEnumerable<String> MachineList { get; }
/// <summary>
/// 机器分组创建时间。
/// </summary>
public Int32 CreateTime { get; }
/// <summary>
/// 机器分组最近更新时间。
/// </summary>
public Int32 LastModifyTime { get; }
public GetMachineGroupResult(String groupName, String groupType, MachineGroupAttributeInfo groupAttribute, String machineIdentifyType,
IEnumerable<String> machineList, Int32 createTime, Int32 lastModifyTime)
{
this.GroupName = groupName;
this.GroupType = groupType;
this.GroupAttribute = groupAttribute;
this.MachineIdentifyType = machineIdentifyType;
this.MachineList = machineList;
this.CreateTime = createTime;
this.LastModifyTime = lastModifyTime;
}
}
}

View File

@@ -0,0 +1,52 @@
//
// ListMachineGroupRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class ListMachineGroupRequest : ProjectScopedRequest
{
public const Int32 DefaultOffset = 0;
public const Int32 DefaultSize = 500;
/// <summary>
/// 用于过滤的机器组名称(支持部分匹配)。
/// </summary>
public String GroupName { get; set; }
/// <summary>
/// 返回记录的起始位置,默认为 0。
/// </summary>
public Int32 Offset { get; set; } = DefaultOffset;
/// <summary>
/// 每页返回最大条目,默认 500最大值
/// </summary>
public Int32 Size { get; set; } = DefaultSize;
}
}

View File

@@ -0,0 +1,56 @@
//
// ListMachineGroupResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class ListMachineGroupResult
{
/// <summary>
/// 返回的 machinegroup 数目。
/// </summary>
public Int32 Count { get; }
/// <summary>
/// 返回 machinegroup 总数。
/// </summary>
public Int32 Total { get; }
/// <summary>
/// 返回的 machinegroup 名称列表。
/// </summary>
public IList<String> MachineGroups { get; }
public ListMachineGroupResult(Int32 count, Int32 total, IList<String> machineGroups)
{
this.Count = count;
this.Total = total;
this.MachineGroups = machineGroups;
}
}
}

View File

@@ -0,0 +1,57 @@
//
// ListMachinesRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class ListMachinesRequest : ProjectScopedRequest
{
public const Int32 DefaultOffset = 0;
public const Int32 DefaultSize = 500;
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
/// <summary>
/// 返回记录的起始位置,默认为 0。
/// </summary>
public Int32 Offset { get; set; } = DefaultOffset;
/// <summary>
/// 每页返回最大条目,默认 500最大值
/// </summary>
public Int32 Size { get; set; } = DefaultSize;
public ListMachinesRequest(String groupName)
{
this.GroupName = groupName;
}
}
}

View File

@@ -0,0 +1,87 @@
//
// ListMachinesResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class ListMachinesResult
{
/// <summary>
/// 返回的 machinegroup 数目。
/// </summary>
public Int32 Count { get; }
/// <summary>
/// 返回 machinegroup 总数。
/// </summary>
public Int32 Total { get; }
/// <summary>
/// 返回的 machinegroup 名称列表。
/// </summary>
public IList<MachineInfo> Machines { get; }
public ListMachinesResult(Int32 count, Int32 total, IList<MachineInfo> machines)
{
this.Count = count;
this.Total = total;
this.Machines = machines;
}
public class MachineInfo
{
/// <summary>
/// 机器的 IP。
/// </summary>
public String Ip { get; }
/// <summary>
/// 机器 DMI UUID。
/// </summary>
public String MachineUniqueId { get; }
/// <summary>
/// 机器的用户自定义标识。
/// </summary>
public String UserDefinedId { get; }
/// <summary>
/// 机器最后的心跳时间。
/// </summary>
public String LastHeartbeatTime { get; }
public MachineInfo(String ip, String machineUniqueId, String userDefinedId, String lastHeartbeatTime)
{
this.Ip = ip;
this.MachineUniqueId = machineUniqueId;
this.UserDefinedId = userDefinedId;
this.LastHeartbeatTime = lastHeartbeatTime;
}
}
}
}

View File

@@ -0,0 +1,43 @@
//
// MachineGroupAttributeInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class MachineGroupAttributeInfo
{
/// <summary>
/// 机器分组的 topic默认为空。
/// </summary>
public String GroupTopic { get; set; }
/// <summary>
/// 机器分组所依赖的外部管理标识,默认为空。
/// </summary>
public String ExternalName { get; set; }
}
}

View File

@@ -0,0 +1,50 @@
//
// RemoveConfigFromMachineGroupRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class RemoveConfigFromMachineGroupRequest : ProjectScopedRequest
{
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
/// <summary>
/// 日志配置名称。
/// </summary>
public String ConfigName { get; }
public RemoveConfigFromMachineGroupRequest(String groupName, String configName)
{
this.GroupName = groupName;
this.ConfigName = configName;
}
}
}

View File

@@ -0,0 +1,67 @@
//
// UpdateMachineGroupRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using Aliyun.Api.LogService.Domain.Project;
namespace Aliyun.Api.LogService.Domain.MachineGroup
{
public class UpdateMachineGroupRequest : ProjectScopedRequest
{
/// <summary>
/// 机器分组名称。
/// </summary>
public String GroupName { get; }
/// <summary>
/// 机器分组类型,默认为空。
/// </summary>
public String GroupType { get; set; }
/// <summary>
/// 机器标识类型,分为 IP 和 userdefined 两种。
/// </summary>
public String MachineIdentifyType { get; }
/// <summary>
/// 机器分组的属性,默认为空。
/// </summary>
public MachineGroupAttributeInfo GroupAttribute { get; set; }
/// <summary>
/// 具体的机器标识,可以是 IP 或 userdefined-id。
/// </summary>
public IEnumerable<String> MachineList { get; }
public UpdateMachineGroupRequest(String groupName, String machineIdentifyType, IEnumerable<String> machineList)
{
this.GroupName = groupName;
this.MachineIdentifyType = machineIdentifyType;
this.MachineList = machineList;
}
}
}

View File

@@ -0,0 +1,49 @@
//
// CreateProjectRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.Project
{
public class CreateProjectRequest
{
/// <summary>
/// project的名称全局唯一。
/// </summary>
public String ProjectName { get; }
/// <summary>
/// project描述。
/// </summary>
public String ProjectDesc { get; }
public CreateProjectRequest(String projectName, String projectDesc)
{
this.ProjectName = projectName;
this.ProjectDesc = projectDesc;
}
}
}

View File

@@ -0,0 +1,32 @@
//
// DeleteProjectRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Domain.Project
{
public class DeleteProjectRequest : ProjectScopedRequest
{
}
}

View File

@@ -0,0 +1,32 @@
//
// GetProjectRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Domain.Project
{
public class GetProjectRequest : ProjectScopedRequest
{
}
}

View File

@@ -0,0 +1,41 @@
//
// GetProjectResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Domain.Project
{
public class GetProjectResult
{
/// <summary>
/// Project信息。
/// </summary>
public ProjectDetailInfo Project { get; }
public GetProjectResult(ProjectDetailInfo project)
{
this.Project = project;
}
}
}

View File

@@ -0,0 +1,51 @@
//
// ListProjectRequest.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.Project
{
public class ListProjectRequest
{
public const Int32 DefaultOffset = 0;
public const Int32 DefaultSize = 500;
/// <summary>
/// 请求结果的起始位置默认为0。
/// </summary>
public Int32 Offset { get; set; } = DefaultOffset;
/// <summary>
/// 每次请求返回结果最大数量默认500最大值
/// </summary>
public Int32 Size { get; set; } = DefaultSize;
/// <summary>
/// 用于过滤返回结果的project名称支持部分匹配
/// </summary>
public String ProjectName { get; set; }
}
}

View File

@@ -0,0 +1,56 @@
//
// ListProjectResult.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Aliyun.Api.LogService.Domain.Project
{
public class ListProjectResult
{
/// <summary>
/// 返回project数量。
/// </summary>
public Int32 Count { get; }
/// <summary>
/// project总数。
/// </summary>
public Int32 Total { get; }
/// <summary>
/// 返回的project属性列表。
/// </summary>
public IList<ProjectInfo> Projects { get; }
public ListProjectResult(Int32 count, Int32 total, IList<ProjectInfo> projects)
{
this.Count = count;
this.Total = total;
this.Projects = projects;
}
}
}

View File

@@ -0,0 +1,62 @@
//
// ProjectDetailInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.Project
{
public class ProjectDetailInfo : ProjectInfo
{
/// <summary>
/// Project所在区域。
/// </summary>
public String Region { get; }
/// <summary>
/// Project的所有者。
/// </summary>
public String Owner { get; }
/// <summary>
/// Project创建时间。
/// </summary>
public String CreateTime { get; }
/// <summary>
/// Project最后修改时间。
/// </summary>
public String LastModifyTime { get; }
public ProjectDetailInfo(String projectName, ProjectState status, String description, String region, String owner, String createTime, String lastModifyTime)
: base(projectName, status, description)
{
this.Region = region;
this.Owner = owner;
this.CreateTime = createTime;
this.LastModifyTime = lastModifyTime;
}
}
}

View File

@@ -0,0 +1,55 @@
//
// ProjectInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Domain.Project
{
public class ProjectInfo
{
/// <summary>
/// project名称。
/// </summary>
public String ProjectName { get; }
/// <summary>
/// project状态分为"Normal"(正常)和"Disable"(欠费停用)。
/// </summary>
public ProjectState Status { get; }
/// <summary>
/// project描述。
/// </summary>
public String Description { get; }
public ProjectInfo(String projectName, ProjectState status, String description)
{
this.ProjectName = projectName;
this.Status = status;
this.Description = description;
}
}
}

View File

@@ -0,0 +1,43 @@
//
// LogServiceClientBuilders.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Newtonsoft.Json;
namespace Aliyun.Api.LogService.Domain.Project
{
/// <summary>
/// 限定在指定Project内的请求可带有 <see cref="ProjectName"/> 属性,覆盖 <see cref="ILogServiceClient"/> 中默认的 Project。
/// </summary>
public abstract class ProjectScopedRequest
{
/// <summary>
/// 覆盖 <see cref="ILogServiceClient"/> 中默认的 Project。
/// </summary>
[JsonIgnore]
public String ProjectName { get; set; }
}
}

View File

@@ -0,0 +1,41 @@
//
// ProjectState.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Domain.Project
{
public enum ProjectState
{
/// <summary>
/// 正常。
/// </summary>
Normal,
/// <summary>
/// 欠费停用。
/// </summary>
Disable,
}
}

View File

@@ -0,0 +1,357 @@
//
// ILogServiceClient.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using System.Threading.Tasks;
using Aliyun.Api.LogService.Domain.Config;
using Aliyun.Api.LogService.Domain.Log;
using Aliyun.Api.LogService.Domain.LogStore;
using Aliyun.Api.LogService.Domain.LogStore.Index;
using Aliyun.Api.LogService.Domain.LogStore.Shard;
using Aliyun.Api.LogService.Domain.LogStore.Shipper;
using Aliyun.Api.LogService.Domain.MachineGroup;
using Aliyun.Api.LogService.Domain.Project;
using Aliyun.Api.LogService.Infrastructure.Protocol;
namespace Aliyun.Api.LogService
{
public interface ILogServiceClient
{
#region LogStore
/// <summary>
/// 在 Project 下创建 Logstore。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> CreateLogStoreAsync(CreateLogStoreRequest request);
/// <summary>
/// 删除 Logstore包括所有 Shard 数据,以及索引等。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> DeleteLogStoreAsync(DeleteLogStoreRequest request);
/// <summary>
/// 更新 Logstore 的属性。目前只支持更新 TTL和shard 属性。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> UpdateLogStoreAsync(UpdateLogStoreRequest request);
/// <summary>
/// 查看 Logstore 属性。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetLogStoreResult>> GetLogStoreAsync(GetLogStoreRequest request);
/// <summary>
/// 接口列出指定 Project 下的所有 Logstore 的名称。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<ListLogStoreResult>> ListLogStoreAsync(ListLogStoreRequest request);
#region Shard
/// <summary>
/// 列出 Logstore 下当前所有可用 Shard。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<IList<ShardInfo>>> ListShardsAsync(ListShardRequest request);
/// <summary>
/// 分裂一个指定的 readwrite 状态的 Shard。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<IList<ShardInfo>>> SplitShardAsync(SplitShardRequest request);
/// <summary>
/// 合并两个相邻的 readwrite 状态的 Shards。在参数中指定一个 shardid服务端自动找相邻的下一个 Shard。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<IList<ShardInfo>>> MergeShardsAsync(MergeShardRequest request);
/// <summary>
/// 根据时间获得游标cursor
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetCursorResult>> GetCursorAsync(GetCursorRequest request);
#endregion Shard
#region Shipper
/// <summary>
/// 查询日志投递任务状态。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetShipperResult>> GetShipperStatusAsync(GetShipperRequest request);
/// <summary>
/// 重新执行失败的日志投递任务。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> RetryShipperTaskAsync(RetryShipperRequest request);
#endregion Shipper
#region Index
/// <summary>
/// 开启日志库索引。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> CreateIndexAsync(CreateIndexRequest request);
#endregion Index
#endregion LogStore
#region Logs
/// <summary>
/// 向指定的 LogStore 写入日志数据。目前仅支持写入 PB 格式的 <see cref="LogGroupInfo"/> 日志数据。写入时有两种模式:
/// <list type="bullet">
/// <item>
/// <description>负载均衡模式LoadBalance: 自动根据 Logstore 下所有可写的 shard 进行负载均衡写入。该方法对写入可用性较高SLA: 99.95%),适合写入与消费数据与 shard 无关的场景,例如不保序。</description>
/// </item>
/// <item>
/// <description>根据 Key 路由 shard 模式KeyHash写入时需要传递一个 Key服务端自动根据 Key 选择当前符合该 Key 区间的 Shard 写入。例如,可以将某个生产者(例如 instance根据名称 Hash 到固定 Shard 上,这样就能保证写入与消费在该 Shard 上是严格有序的(在 Merge/Split 过程中能够严格保证对于 Key 在一个时间点只会出现在一个 Shard 上,参见 <see ref="http://help.aliyun.com/document_detail/28976.html">shard 数据模型</see>)。</description>
/// </item>
/// </list>
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> PostLogStoreLogsAsync(PostLogsRequest request);
/// <summary>
/// 根据游标、数量获得日志。获得日志时必须指定 shard。
/// 如果在 storm 等情况下可以通过 LoghubClientLib 进行选举与协同消费。
/// 目前仅支持读取 PB 格式 LogGroupList 数据。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<PullLogsResult>> PullLogsAsync(PullLogsRequest request);
/// <summary>
/// GetLogs 接口查询指定 Project 下某个 Logstore 中的日志数据。还可以通过指定相关参数仅查询符合指定条件的日志数据。
/// 当日志写入到 Logstore 中日志服务的查询接口GetHistograms 和 GetLogs能够查到该日志的延时因写入日志类型不同而异。日志服务按日志时间戳把日志分为如下两类
/// <list type="bullet">
/// <item><description>实时数据:日志中时间点为服务器当前时间点 (-180秒900秒]。例如,日志时间为 UTC 2014-09-25 12:03:00服务器收到时为 UTC 2014-09-25 12:05:00则该日志被作为实时数据处理一般出现在正常场景下。</description></item>
/// <item><description>历史数据:日志中时间点为服务器当前时间点 [-7 x 86400秒, -180秒)。例如,日志时间为 UTC 2014-09-25 12:00:00服务器收到时为 UTC 2014-09-25 12:05:00则该日志被作为历史数据处理一般出现在补数据场景下。</description></item>
/// </list>
///
/// 其中实时数据写入至可查询的最大延时为3秒99.9%情况下1秒内即可查询
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
/// <summary>
Task<IResponse<GetLogsResult>> GetLogsAsync(GetLogsRequest request);
/// <summary>
/// 统计Project下所有日志。
/// <list type="bullet">
/// <item><description>该接口的query是一个标准的SQL查询语句。</description></item>
/// <item><description>查询的Project在请求的域名中指定。</description></item>
/// <item><description>查询的logstore在查询语句的from条件中指定。logstore相当于SQL中的表。</description></item>
/// <item><description>在查询的SQL条件中必须指定要查询的时间范围时间范围由__date__(timestamp类型)来指定或__time__(int 类型单位是unix_time)来指定。</description></item>
/// <item><description>如上所述,该接口一次调用必须要在限定时间内返回结果,每次查询只能扫描指定条数的日志量。如果一次请求需要处理的数据量非常大的时候,该请求会返回不完整的结果(并在返回结果中的 x-log-progress 成员标示是否完整)。如此同时,服务端会缓存 15 分钟内的查询结果。当查询请求的结果有部分被缓存命中,则服务端会在这次请求中继续扫描未被缓存命中的日志数据。为了减少您合并多次查询结果的工作量,服务端会把缓存命中的查询结果与本次查询新命中的结果合并返回给您。因此,日志服务可以让您通过以相同参数反复调用该接口来获取最终完整结果。因为您的查询涉及的日志数据量变化非常大,日志服务 API 无法预测需要调用多少次该接口而获取完整结果。所以需要用户通过检查每次请求的返回结果中的x-log-progress成员状态值来确定是否需要继续。需要注意的是每次重复调用该接口都会重新消耗相同数量的查询 CU。</description></item>
/// </list>
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetLogsResult>> GetProjectLogsAsync(GetProjectLogsRequest request);
/// <summary>
/// GetHistograms 接口查询指定的 Project 下某个 Logstore 中日志的分布情况。还可以通过指定相关参数仅查询符合指定条件的日志分布情况。
/// 当日志写入到 logstore 中日志服务的查询接口GetHistograms 和 GetLogs能够查到该日志的延时因写入日志类型不同而异。日志服务按日志时间戳把日志分为如下两类
/// <list type="bullet">
/// <item><description>实时数据:日志中时间点为服务器当前时间点 (-180秒900秒]。例如,日志时间为 UTC 2014-09-25 12:03:00服务器收到时为 UTC 2014-09-25 12:05:00则该日志被作为实时数据处理一般出现在正常场景下。</description></item>
/// <item><description>历史数据:日志中时间点为服务器当前时间点 [-7 x 86400秒, -180秒)。例如,日志时间为 UTC 2014-09-25 12:00:00服务器收到时为 UTC 2014-09-25 12:05:00则该日志被作为历史数据处理一般出现在补数据场景下。</description></item>
/// </list>
///
/// 其中实时数据写入至可查询的延时为3秒。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetLogHistogramsResult>> GetHistogramsAsync(GetLogHistogramsRequest request);
#endregion Logs
#region MachineGroup
/// <summary>
/// 根据需求创建一组机器,用以日志收集下发配置。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> CreateMachineGroupAsync(CreateMachineGroupRequest request);
/// <summary>
/// 删除机器组,如果机器组上有配置,则 Logtail 上对应的配置也会被删除。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> DeleteMachineGroupAsync(DeleteMachineGroupRequest request);
/// <summary>
/// 更新机器组信息,如果机器组已应用配置,则新加入、减少机器会自动增加、移除配置。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> UpdateMachineGroupAsync(UpdateMachineGroupRequest request);
/// <summary>
/// 列出 MachineGroup 信息。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<ListMachineGroupResult>> ListMachineGroupAsync(ListMachineGroupRequest request);
/// <summary>
/// 查看具体的 MachineGroup 信息。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetMachineGroupResult>> GetMachineGroupAsync(GetMachineGroupRequest request);
/// <summary>
/// 将配置应用到机器组。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> ApplyConfigToMachineGroupAsync(ApplyConfigToMachineGroupRequest request);
/// <summary>
/// 从机器组中删除配置。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> RemoveConfigFromMachineGroupAsync(RemoveConfigFromMachineGroupRequest request);
/// <summary>
/// 获得 MachineGroup 下属于用户并与 Server 端连接的机器状态信息。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<ListMachinesResult>> ListMachinesAsync(ListMachinesRequest request);
/// <summary>
/// 获得 MachineGroup 上已经被应用的配置名称。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetAppliedConfigsResult>> GetAppliedConfigsAsync(GetAppliedConfigsRequest request);
#endregion MachineGroup
#region Config
/// <summary>
/// 在 Project 下创建日志配置。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> CreateConfigAsync(CreateConfigRequest request);
/// <summary>
/// 列出 Project 下所有配置信息,可以通过参数进行翻页。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<ListConfigResult>> ListConfigAsync(ListConfigRequest request);
/// <summary>
/// 列出 config 应用的机器列表。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetAppliedMachineGroupsResult>> GetAppliedMachineGroupsAsync(GetAppliedMachineGroupsRequest request);
/// <summary>
/// 获得一个配置的详细信息。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetConfigResult>> GetConfigAsync(GetConfigRequest request);
/// <summary>
/// 删除特定 config如果 config 已被 应用到机器组,则 Logtail 配置也会被删除。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> DeleteConfigAsync(DeleteConfigRequest request);
/// <summary>
/// 更新配置内容,如果配置被应用到机器组,对应机器也会同时更新。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> UpdateConfigAsync(UpdateConfigRequest request);
#endregion Config
#region Project
/// <summary>
/// 创建project。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> CreateProjectAsync(CreateProjectRequest request);
/// <summary>
/// 获取指定区域Project列表。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<ListProjectResult>> ListProjectAsync(ListProjectRequest request);
/// <summary>
/// 获取当前Project信息。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse<GetProjectResult>> GetProjectAsync(GetProjectRequest request);
/// <summary>
/// 删除当前Project。
/// </summary>
/// <param name="request">请求报文。</param>
/// <returns>异步响应结果。</returns>
Task<IResponse> DeleteProjectAsync(DeleteProjectRequest request);
#endregion
}
}

View File

@@ -0,0 +1,49 @@
//
// LogServiceClientBuilders.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Infrastructure.Authentication
{
/// <summary>
/// 身份验证凭据。
/// </summary>
public class Credential
{
public String AccessKeyId { get; }
public String AccessKey { get; }
public String StsToken { get; }
public Credential(String accessKeyId, String accessKey, String stsToken = null)
{
this.AccessKeyId = accessKeyId;
this.AccessKey = accessKey;
this.StsToken = stsToken;
}
}
}

View File

@@ -0,0 +1,52 @@
//
// CompressType.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Infrastructure.Protocol
{
/// <summary>
/// 数据压缩类型。
/// </summary>
public enum CompressType
{
/// <summary>
/// 无压缩(默认)
/// </summary>
None,
/// <summary>
/// 使用标准LZ4压缩方式。
/// </summary>
/// <seealso ref="http://wikipedia.org/wiki/LZ4_(compression_algorithm)"/>
Lz4,
/// <summary>
/// 使用DeflateZlib包装RFC 1950压缩方式。
/// </summary>
/// <seealso ref="http://www.ietf.org/rfc/rfc1950.txt"/>
/// <seealso ref="http://www.ietf.org/rfc/rfc1951.txt"/>
Deflate,
}
}

View File

@@ -0,0 +1,55 @@
//
// Error.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Aliyun.Api.LogService.Infrastructure.Protocol
{
/// <summary>
/// 错误信息
/// </summary>
public class Error
{
/// <summary>
/// 错误码
/// </summary>
public ErrorCode ErrorCode { get; }
/// <summary>
/// 错误消息
/// </summary>
public String ErrorMessage { get; }
public Error(ErrorCode errorCode, String errorMessage)
{
this.ErrorCode = errorCode;
this.ErrorMessage = errorMessage;
}
public override String ToString()
=> $"{this.ErrorCode}{(this.ErrorMessage == null ? String.Empty : $" ({this.ErrorMessage})")}";
}
}

View File

@@ -0,0 +1,229 @@
//
// ErrorCode.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Aliyun.Api.LogService.Infrastructure.Protocol
{
public class ErrorCode
{
#region Known error codes
/// <summary>
/// SDK 内部错误。
/// </summary>
internal static ErrorCode SdkInternalError { get; } = new ErrorCode(nameof(SdkInternalError));
///<summary>
///没有提供必须的 Content-Length 请求头。
///</summary>
public static ErrorCode MissingContentLength { get; } = new ErrorCode(nameof(MissingContentLength));
///<summary>
///不支持 Content-Type 指定的类型。
///</summary>
public static ErrorCode InvalidContentType { get; } = new ErrorCode(nameof(InvalidContentType));
///<summary>
///没有为 Body 不为空的 HTTP 请求指定 Content-Type 头。
///</summary>
public static ErrorCode MissingContentType { get; } = new ErrorCode(nameof(MissingContentType));
///<summary>
///压缩场景下没有提供必须的 x-log-bodyrawsize 请求头。
///</summary>
public static ErrorCode MissingBodyRawSize { get; } = new ErrorCode(nameof(MissingBodyRawSize));
///<summary>
///x-log-bodyrawsize 的值无效。
///</summary>
public static ErrorCode InvalidBodyRawSize { get; } = new ErrorCode(nameof(InvalidBodyRawSize));
///<summary>
///x-log-compresstype 指定的压缩方式不支持。
///</summary>
public static ErrorCode InvalidCompressType { get; } = new ErrorCode(nameof(InvalidCompressType));
///<summary>
///没有提供 HTTP 标准请求头 Host。
///</summary>
public static ErrorCode MissingHost { get; } = new ErrorCode(nameof(MissingHost));
///<summary>
///没有提供 HTTP 标准请求头 Date。
///</summary>
public static ErrorCode MissingDate { get; } = new ErrorCode(nameof(MissingDate));
///<summary>
///Date 请求头的值不符合 RFC822 标准。
///</summary>
public static ErrorCode InvalidDateFormat { get; } = new ErrorCode(nameof(InvalidDateFormat));
///<summary>
///没有提供 HTTP 请求头 x-log-apiversion。
///</summary>
public static ErrorCode MissingAPIVersion { get; } = new ErrorCode(nameof(MissingAPIVersion));
///<summary>
///HTTP 请求头 x-log-apiversion 的值不支持。
///</summary>
public static ErrorCode InvalidAPIVersion { get; } = new ErrorCode(nameof(InvalidAPIVersion));
///<summary>
///没有在 Authorization 头部提供 AccessKeyId。
///</summary>
public static ErrorCode MissAccessKeyId { get; } = new ErrorCode(nameof(MissAccessKeyId));
///<summary>
///提供的 AccessKeyId 值未授权。
///</summary>
public static ErrorCode Unauthorized { get; } = new ErrorCode(nameof(Unauthorized));
///<summary>
///没有提供 HTTP 请求头 x-log-signaturemethod。
///</summary>
public static ErrorCode MissingSignatureMethod { get; } = new ErrorCode(nameof(MissingSignatureMethod));
///<summary>
///x-log-signaturemethod 头部指定的签名方法不支持。
///</summary>
public static ErrorCode InvalidSignatureMethod { get; } = new ErrorCode(nameof(InvalidSignatureMethod));
///<summary>
///请求的发送时间超过当前服务处理时间前后 15 分钟的范围。
///</summary>
public static ErrorCode RequestTimeTooSkewed { get; } = new ErrorCode(nameof(RequestTimeTooSkewed));
///<summary>
///日志项目Project不存在。
///</summary>
public static ErrorCode ProjectNotExist { get; } = new ErrorCode(nameof(ProjectNotExist));
///<summary>
///请求的数字签名不匹配。
///</summary>
public static ErrorCode SignatureNotMatch { get; } = new ErrorCode(nameof(SignatureNotMatch));
///<summary>
///超过写入日志限额。
///</summary>
public static ErrorCode WriteQuotaExceed { get; } = new ErrorCode(nameof(WriteQuotaExceed));
///<summary>
///超过读取日志限额。
///</summary>
public static ErrorCode ReadQuotaExceed { get; } = new ErrorCode(nameof(ReadQuotaExceed));
///<summary>
///服务器内部错误。
///</summary>
public static ErrorCode InternalServerError { get; } = new ErrorCode(nameof(InternalServerError));
///<summary>
///服务器正忙,请稍后再试。
///</summary>
public static ErrorCode ServerBusy { get; } = new ErrorCode(nameof(ServerBusy));
#endregion
private static readonly IDictionary<String, ErrorCode> KnownErrorCodes;
public String Code { get; }
static ErrorCode()
{
KnownErrorCodes = new Dictionary<String, ErrorCode>(typeof(ErrorCode)
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
.Where(x => x.PropertyType == typeof(ErrorCode))
.Select(x => x.GetValue(null))
.Cast<ErrorCode>()
.ToDictionary(x => x.Code, x => x));
}
private ErrorCode(String code)
{
this.Code = code;
}
public static Boolean IsKnownErrorCode(String code)
{
return KnownErrorCodes.ContainsKey(code);
}
public Boolean IsKnownErrorCode()
{
return IsKnownErrorCode(this.Code);
}
public override Boolean Equals(Object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
switch (obj)
{
case ErrorCode other:
return String.Equals(this.Code, other.Code);
case String other:
return String.Equals(this.Code, other);
default:
return false;
}
}
public override Int32 GetHashCode()
=> this.Code?.GetHashCode() ?? 0;
public override String ToString()
=> this.Code;
public static implicit operator String(ErrorCode code)
=> code?.Code;
public static implicit operator ErrorCode(String code)
=> code == null
? null
: (KnownErrorCodes.TryGetValue(code, out var errorCode)
? errorCode
: new ErrorCode(code));
public static Boolean operator ==(ErrorCode lhs, ErrorCode rhs)
=> lhs?.Code == rhs?.Code;
public static Boolean operator !=(ErrorCode lhs, ErrorCode rhs)
=> lhs?.Code != rhs?.Code;
}
}

View File

@@ -0,0 +1,439 @@
//
// HttpLogServiceClient.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Aliyun.Api.LogService.Domain.Config;
using Aliyun.Api.LogService.Domain.Log;
using Aliyun.Api.LogService.Domain.LogStore;
using Aliyun.Api.LogService.Domain.LogStore.Index;
using Aliyun.Api.LogService.Domain.LogStore.Shard;
using Aliyun.Api.LogService.Domain.LogStore.Shipper;
using Aliyun.Api.LogService.Domain.MachineGroup;
using Aliyun.Api.LogService.Domain.Project;
using Aliyun.Api.LogService.Infrastructure.Authentication;
using Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf;
using Aliyun.Api.LogService.Utils;
using Newtonsoft.Json;
namespace Aliyun.Api.LogService.Infrastructure.Protocol.Http
{
public class HttpLogServiceClient : ILogServiceClient
{
private readonly HttpClient httpClient;
private readonly Func<Credential> credentialProvider;
public HttpLogServiceClient(HttpClient httpClient, Func<Credential> credentialProvider)
{
this.httpClient = httpClient;
this.credentialProvider = credentialProvider;
}
#region Helper
private async Task<TResponse> SendRequestAsync<TResponse>(IRequestBuilder<HttpRequestMessage> requestBuilder,
Func<IResponseResolver, Task<TResponse>> resposneResolver, Boolean outOfProject = false, String project = null)
{
var credential = this.credentialProvider();
var httpRequestMessage = requestBuilder
.Authenticate(credential)
.Sign(SignatureType.HmacSha1)
.Build();
if (outOfProject)
{
httpRequestMessage.Headers.Host = this.httpClient.BaseAddress.Host;
} else if (project.IsNotEmpty())
{
httpRequestMessage.Headers.Host = $"{project}.{this.httpClient.BaseAddress.Host}";
}
var responseMessage = await this.httpClient.SendAsync(httpRequestMessage);
return await resposneResolver(HttpResponseMessageResolver.For(responseMessage));
}
private Task<IResponse> SendRequestAsync(IRequestBuilder<HttpRequestMessage> requestBuilder, Boolean outOfProject = false, String project = null)
=> this.SendRequestAsync(requestBuilder, x => x.ResolveAsync(), outOfProject, project);
private Task<IResponse<TResult>> SendRequestAsync<TResult>(IRequestBuilder<HttpRequestMessage> requestBuilder, Boolean outOfProject = false, String project = null)
where TResult : class
=> this.SendRequestAsync(requestBuilder, x => x.With<TResult>().ResolveAsync(), outOfProject, project);
#endregion
#region LogStore
public Task<IResponse> CreateLogStoreAsync(CreateLogStoreRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Post, "/logstores")
.Content(request)
.Serialize(SerializeType.Json),
project:request.ProjectName);
public Task<IResponse> DeleteLogStoreAsync(DeleteLogStoreRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Delete, $"/logstores/{request.LogstoreName}"),
project:request.ProjectName);
public Task<IResponse> UpdateLogStoreAsync(UpdateLogStoreRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Put, $"/logstores/{request.LogstoreName}")
.Content(request)
.Serialize(SerializeType.Json),
project:request.ProjectName);
public Task<IResponse<GetLogStoreResult>> GetLogStoreAsync(GetLogStoreRequest request)
=> this.SendRequestAsync<GetLogStoreResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/logstores/{request.LogstoreName}"),
project:request.ProjectName);
public Task<IResponse<ListLogStoreResult>> ListLogStoreAsync(ListLogStoreRequest request)
=> this.SendRequestAsync<ListLogStoreResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, "/logstores")
.Query(request),
project:request.ProjectName);
#region Shard
public Task<IResponse<IList<ShardInfo>>> ListShardsAsync(ListShardRequest request)
=> this.SendRequestAsync<IList<ShardInfo>>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/logstores/{request.LogstoreName}/shards"),
project:request.ProjectName);
public Task<IResponse<IList<ShardInfo>>> SplitShardAsync(SplitShardRequest request)
=> this.SendRequestAsync<IList<ShardInfo>>(
new HttpRequestMessageBuilder(HttpMethod.Post, $"/logstores/{request.LogstoreName}/shards/{request.ShardId}")
.Query("action", "split")
.Query("key", request.SplitKey),
project:request.ProjectName);
public Task<IResponse<IList<ShardInfo>>> MergeShardsAsync(MergeShardRequest request)
=> this.SendRequestAsync<IList<ShardInfo>>(
new HttpRequestMessageBuilder(HttpMethod.Post, $"/logstores/{request.LogstoreName}/shards/{request.ShardId}")
.Query("action", "merge"),
project:request.ProjectName);
public Task<IResponse<GetCursorResult>> GetCursorAsync(GetCursorRequest request)
=> this.SendRequestAsync<GetCursorResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/logstores/{request.LogstoreName}/shards/{request.ShardId}")
.Query("type", "cursor")
.Query("from", request.From),
project:request.ProjectName);
#endregion Shard
#region Shipper
public Task<IResponse<GetShipperResult>> GetShipperStatusAsync(GetShipperRequest request)
=> this.SendRequestAsync<GetShipperResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/logstores/{request.LogstoreName}/shipper/{request.ShipperName}/tasks")
.Query("from", request.From.ToString())
.Query("to", request.To.ToString())
.Query("status", request.Status)
.Query("offset", request.Offset.ToString())
.Query("size", request.Size.ToString()),
project:request.ProjectName);
public Task<IResponse> RetryShipperTaskAsync(RetryShipperRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Put, $"/logstores/{request.LogstoreName}/shipper/{request.ShipperName}/tasks")
.Content(request.TaskIds)
.Serialize(SerializeType.Json),
project:request.ProjectName);
#endregion Shipper
#region Index
public Task<IResponse> CreateIndexAsync(CreateIndexRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Post, $"/logstores/{request.LogstoreName}/index")
.Content(request)
.Serialize(SerializeType.Json),
project:request.ProjectName);
#endregion Index
#endregion LogStore
#region Logs
public Task<IResponse> PostLogStoreLogsAsync(PostLogsRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Post, request.HashKey.IsEmpty()
? $"/logstores/{request.LogstoreName}/shards/lb"
: $"/logstores/{request.LogstoreName}/shards/route?key={request.HashKey}")
.Content(request.LogGroup.ToProtoModel())
.Serialize(SerializeType.Protobuf)
.Compress(CompressType.Lz4),
project:request.ProjectName);
public Task<IResponse<PullLogsResult>> PullLogsAsync(PullLogsRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/logstores/{request.LogstoreName}/shards/{request.ShardId}")
.Query("type", "logs")
.Query("cursor", request.Cursor)
.Query("count", request.Count.ToString())
.Header("Accept", "application/x-protobuf")
.Header("Accept-Encoding", "lz4"),
resolver => resolver
.Deserialize(x => LogGroupList.Parser.ParseFrom(x))
.ResolveAsync(x => new PullLogsResult(x.ToDomainModel())),
project:request.ProjectName);
public async Task<IResponse<GetLogsResult>> GetLogsAsync(GetLogsRequest request)
=> (await this.SendRequestAsync<IList<IDictionary<String, String>>>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/logstores/{request.Logstorename}")
.Query("type", "log")
.Query("from", request.From.ToString())
.Query("to", request.To.ToString())
.Query("topic", request.Topic)
.Query("query", request.Query)
.Query("line", request.Line.ToString())
.Query("offset", request.Offset.ToString())
.Query("reverse", request.Reverse.ToString()),
project:request.ProjectName))
.Transform((httpHeaders, data) =>
{
var newResult = new GetLogsResult(data)
{
Count = Convert.ToInt32(httpHeaders.GetValueOrDefault(LogHeaders.Count)),
ProcessedRows = Convert.ToInt32(httpHeaders.GetValueOrDefault(LogHeaders.ProcessedRows)),
ElapsedMillisecond = Convert.ToInt32(httpHeaders.GetValueOrDefault(LogHeaders.ElapsedMillisecond)),
HasSql = Convert.ToBoolean(httpHeaders.GetValueOrDefault(LogHeaders.HasSql)),
AggQuery = httpHeaders.GetValueOrDefault(LogHeaders.AggQuery),
WhereQuery = httpHeaders.GetValueOrDefault(LogHeaders.WhereQuery)
};
// Parse Progress
if (Enum.TryParse<LogProgressState>(httpHeaders.GetValueOrDefault(LogHeaders.Progress), true, out var progress))
{
newResult.Progress = progress;
}
// Parse QueryInfo
if (httpHeaders.TryGetValue(LogHeaders.QueryInfo, out var queryInfoValue))
{
newResult.QueryInfo = JsonConvert.DeserializeObject<LogQueryInfo>(queryInfoValue);
}
return newResult;
});
public async Task<IResponse<GetLogsResult>> GetProjectLogsAsync(GetProjectLogsRequest request)
=> (await this.SendRequestAsync<IList<IDictionary<String, String>>>(
new HttpRequestMessageBuilder(HttpMethod.Get, "/logs")
.Query(request),
project:request.ProjectName))
.Transform((httpHeaders, data) =>
{
var newResult = new GetLogsResult(data)
{
Count = Convert.ToInt32(httpHeaders.GetValueOrDefault(LogHeaders.Count)),
ProcessedRows = Convert.ToInt32(httpHeaders.GetValueOrDefault(LogHeaders.ProcessedRows)),
ElapsedMillisecond = Convert.ToInt32(httpHeaders.GetValueOrDefault(LogHeaders.ElapsedMillisecond)),
HasSql = Convert.ToBoolean(httpHeaders.GetValueOrDefault(LogHeaders.HasSql)),
AggQuery = httpHeaders.GetValueOrDefault(LogHeaders.AggQuery),
WhereQuery = httpHeaders.GetValueOrDefault(LogHeaders.WhereQuery)
};
// Parse Progress
if (Enum.TryParse<LogProgressState>(httpHeaders.GetValueOrDefault(LogHeaders.Progress), true, out var progress))
{
newResult.Progress = progress;
}
// Parse QueryInfo
if (httpHeaders.TryGetValue(LogHeaders.QueryInfo, out var queryInfoValue))
{
newResult.QueryInfo = JsonConvert.DeserializeObject<LogQueryInfo>(queryInfoValue);
}
return newResult;
});
public async Task<IResponse<GetLogHistogramsResult>> GetHistogramsAsync(GetLogHistogramsRequest request)
=> (await this.SendRequestAsync<IList<LogHistogramInfo>>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/logstores/{request.Logstorename}")
.Query("type", "histogram")
.Query("from", request.From.ToString())
.Query("to", request.To.ToString())
.Query("topic", request.Topic)
.Query("query", request.Query),
project:request.ProjectName))
.Transform((httpHeaders, data) =>
{
var newResult = new GetLogHistogramsResult(data)
{
Count = Convert.ToInt32(httpHeaders.GetValueOrDefault(LogHeaders.Count))
};
// Parse Progress
if (Enum.TryParse<LogProgressState>(httpHeaders.GetValueOrDefault(LogHeaders.Progress), true, out var progress))
{
newResult.Progress = progress;
}
return newResult;
});
#endregion Logs
#region MachineGroup
public Task<IResponse> CreateMachineGroupAsync(CreateMachineGroupRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Post, "/machinegroups")
.Content(request)
.Serialize(SerializeType.Json),
project:request.ProjectName);
public Task<IResponse> DeleteMachineGroupAsync(DeleteMachineGroupRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Delete, $"/machinegroups/{request.GroupName}"),
project:request.ProjectName);
public Task<IResponse> UpdateMachineGroupAsync(UpdateMachineGroupRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Put, $"/machinegroups/{request.GroupName}")
.Content(request)
.Serialize(SerializeType.Json),
project:request.ProjectName);
public Task<IResponse<ListMachineGroupResult>> ListMachineGroupAsync(ListMachineGroupRequest request)
=> this.SendRequestAsync<ListMachineGroupResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, "/machinegroups")
.Query(request),
project:request.ProjectName);
public Task<IResponse<GetMachineGroupResult>> GetMachineGroupAsync(GetMachineGroupRequest request)
=> this.SendRequestAsync<GetMachineGroupResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/machinegroups/{request.GroupName}"));
public Task<IResponse> ApplyConfigToMachineGroupAsync(ApplyConfigToMachineGroupRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Put, $"/machinegroups/{request.GroupName}/configs/{request.ConfigName}"),
project:request.ProjectName);
public Task<IResponse> RemoveConfigFromMachineGroupAsync(RemoveConfigFromMachineGroupRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Delete, $"/machinegroups/{request.GroupName}/configs/{request.ConfigName}"),
project:request.ProjectName);
public Task<IResponse<ListMachinesResult>> ListMachinesAsync(ListMachinesRequest request)
=> this.SendRequestAsync<ListMachinesResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/machinegroups/{request.GroupName}/machines")
.Query("offset", request.Offset.ToString())
.Query("size", request.Size.ToString()),
project:request.ProjectName);
public Task<IResponse<GetAppliedConfigsResult>> GetAppliedConfigsAsync(GetAppliedConfigsRequest request)
=> this.SendRequestAsync<GetAppliedConfigsResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/machinegroups/{request.GroupName}/configs"),
project:request.ProjectName);
#endregion MachineGroup
#region Config
public Task<IResponse> CreateConfigAsync(CreateConfigRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Post, "/configs")
.Content(request)
.Serialize(SerializeType.Json),
project:request.ProjectName);
public Task<IResponse<ListConfigResult>> ListConfigAsync(ListConfigRequest request)
=> this.SendRequestAsync<ListConfigResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, "/configs")
.Query(request),
project:request.ProjectName);
public Task<IResponse<GetAppliedMachineGroupsResult>> GetAppliedMachineGroupsAsync(GetAppliedMachineGroupsRequest request)
=> this.SendRequestAsync<GetAppliedMachineGroupsResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/configs/{request.ConfigName}/machinegroups"),
project:request.ProjectName);
public Task<IResponse<GetConfigResult>> GetConfigAsync(GetConfigRequest request)
=> this.SendRequestAsync<GetConfigResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, $"/configs/{request.ConfigName}"),
project:request.ProjectName);
public Task<IResponse> DeleteConfigAsync(DeleteConfigRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Delete, $"/configs/{request.ConfigName}"),
project:request.ProjectName);
public Task<IResponse> UpdateConfigAsync(UpdateConfigRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Put, $"/configs/{request.ConfigName}")
.Content(request)
.Serialize(SerializeType.Json),
project:request.ProjectName);
#endregion Config
#region Project
public Task<IResponse> CreateProjectAsync(CreateProjectRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Post, "/")
.Content(request)
.Serialize(SerializeType.Json),
outOfProject: true);
public Task<IResponse<ListProjectResult>> ListProjectAsync(ListProjectRequest request)
=> this.SendRequestAsync<ListProjectResult>(
new HttpRequestMessageBuilder(HttpMethod.Get, "/")
.Query(request),
outOfProject: true);
public Task<IResponse<GetProjectResult>> GetProjectAsync(GetProjectRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Get, "/"),
resolver => resolver
.With<ProjectDetailInfo>()
.ResolveAsync(x => new GetProjectResult(x)),
project: request.ProjectName);
public Task<IResponse> DeleteProjectAsync(DeleteProjectRequest request)
=> this.SendRequestAsync(
new HttpRequestMessageBuilder(HttpMethod.Delete, "/"),
project: request.ProjectName);
#endregion Project
}
}

View File

@@ -0,0 +1,242 @@
//
// HttpLogServiceClientBuilder.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Net;
using System.Net.Http;
using Aliyun.Api.LogService.Infrastructure.Authentication;
using Aliyun.Api.LogService.Utils;
namespace Aliyun.Api.LogService.Infrastructure.Protocol.Http
{
public class HttpLogServiceClientBuilder
{
private Uri endpoint;
private Func<Credential> credentialProvider;
private Boolean? useProxy;
private WebProxy proxy;
private TimeSpan? timeout;
/// <summary>
/// 设置服务入口地址以及项目名称。
/// </summary>
/// <param name="endpoint">服务入口地址协议部分可以忽略支持如end.point 或 http://end.point 或 https://end.point。</param>
/// <param name="project">项目名称。</param>
/// <returns>当前实例。</returns>
public HttpLogServiceClientBuilder Endpoint(String endpoint, String project)
{
Ensure.NotEmpty(endpoint, nameof(endpoint));
Ensure.NotEmpty(project, nameof(project));
this.endpoint = parseUri(endpoint, project);
return this;
}
private Uri parseUri(String endpoint, String project)
{
Uri uri;
if (endpoint.StartsWith("http://"))
{
uri = new UriBuilder(endpoint.Insert(7, project + ".")).Uri;
} else if (endpoint.StartsWith("https://"))
{
uri = new UriBuilder(endpoint.Insert(8, project + ".")).Uri;
} else
{
uri = new UriBuilder("http://" + project + "." + endpoint).Uri;
}
return uri;
}
/// <summary>
/// 设置服务入口地址以及项目名称。
/// </summary>
/// <param name="endpoint">服务入口地址。</param>
/// <param name="project">项目名称。</param>
/// <returns>当前实例。</returns>
public HttpLogServiceClientBuilder Endpoint(Uri endpoint, String project)
{
Ensure.NotNull(endpoint, nameof(endpoint));
Ensure.NotEmpty(project, nameof(project));
this.endpoint = parseUri(endpoint.Host, project);
return this;
}
/// <summary>
/// 设置服务使用的 accessKeyId 和 accessKey此方法设置的凭据只能用于 RAM 模式下的主账号/子账号的访问。
/// 跨账号访问需要使用 STS 模式并定时刷新凭据信息,<see cref="Credential(Func{Aliyun.Api.LogService.Infrastructure.Authentication.Credential})"/>。
/// </summary>
/// <param name="accessKeyId">accessKeyId。</param>
/// <param name="accessKey">accessKey。</param>
/// <returns>当前实例。</returns>
public HttpLogServiceClientBuilder Credential(String accessKeyId, String accessKey)
{
Ensure.NotEmpty(accessKeyId, nameof(accessKeyId));
Ensure.NotEmpty(accessKey, nameof(accessKey));
var credential = new Credential(accessKeyId, accessKey);
this.credentialProvider = () => credential;
return this;
}
/// <summary>
/// 设置服务使用的 accessKeyId、 accessKey 及 stsToken 的动态提供者。
/// 此方法设置的凭据支持 RAM 及 STS 模式。
/// </summary>
/// <param name="credentialProvider">凭据提供者。需要注意的是提供的 <paramref name="credentialProvider"/> 在每次请求中都会被调用,请注意缓存有效的服务凭据。</param>
/// <returns>当前实例。</returns>
public HttpLogServiceClientBuilder Credential(Func<Credential> credentialProvider)
{
Ensure.NotNull(credentialProvider, nameof(credentialProvider));
this.credentialProvider = credentialProvider;
return this;
}
/// <summary>
/// 设置连接是否使用代理。
/// 如果无法确定是否需要使用,或想使用系统默认配置,请跳过此方法的调用即可。
/// </summary>
/// <param name="useProxy"><c>true</c> 表示使用代理,<c>false</c> 表示不使用代理(同时会跳过系统级别的代理设置)。</param>
/// <returns>当前实例。</returns>
public HttpLogServiceClientBuilder UseProxy(Boolean useProxy)
{
this.useProxy = useProxy;
return this;
}
/// <summary>
/// 设置使用代理的信息。
/// 如果 <see cref="UseProxy"/> 设置为 <c>false</c> 则此项设置无意义。
/// </summary>
/// <param name="proxyHost">代理地址(必填)。</param>
/// <param name="proxyPort">代理端口(可选),不填则使用默认端口。</param>
/// <param name="proxyUserName">代理验证用户(可选),不填则跳过验证。</param>
/// <param name="proxyPassword">代理验证密码(可选),不填或者 <paramref name="proxyUserName"/> 为空时跳过验证。</param>
/// <param name="proxyDomain">代理验证域(可选)。</param>
/// <returns>当前实例。</returns>
public HttpLogServiceClientBuilder Proxy(String proxyHost,
Int32? proxyPort = null, String proxyUserName = null, String proxyPassword = null, String proxyDomain = null)
{
Ensure.NotEmpty(proxyHost, nameof(proxyHost));
var webProxy = proxyPort.HasValue
? new WebProxy(proxyHost, proxyPort.Value)
: new WebProxy(proxyHost);
if (proxyUserName.IsNotEmpty())
{
webProxy.Credentials = proxyDomain.IsEmpty()
? new NetworkCredential(proxyUserName, proxyPassword ?? String.Empty)
: new NetworkCredential(proxyUserName, proxyPassword ?? String.Empty, proxyDomain);
}
this.proxy = webProxy;
return this;
}
/// <summary>
/// 设置请求超时时间,单位毫秒,需要使用其它单位的请使用 <see cref="RequestTimeout(TimeSpan)"/>。
/// 如跳过此项设置,则使用底层框架的默认超时时间。
/// </summary>
/// <param name="timeoutMillis">请求超时时间,单位毫秒。</param>
/// <returns>当前实例。</returns>
public HttpLogServiceClientBuilder RequestTimeout(Int32 timeoutMillis)
{
return this.RequestTimeout(TimeSpan.FromMilliseconds(timeoutMillis));
}
/// <summary>
/// 设置请求超时时间。
/// 如跳过此项设置,则使用底层框架的默认超时时间。
/// </summary>
/// <param name="timeout">请求超时时间。</param>
/// <returns>当前实例。</returns>
public HttpLogServiceClientBuilder RequestTimeout(TimeSpan timeout)
{
this.timeout = timeout;
return this;
}
/// <summary>
/// 根据上述设置构建 <see cref="HttpLogServiceClient"/>。
/// </summary>
/// <returns>构建好的 <see cref="HttpLogServiceClient"/>。</returns>
public HttpLogServiceClient Build()
{
Ensure.NotNull(this.endpoint, nameof(this.endpoint));
Ensure.NotNull(this.credentialProvider, nameof(this.credentialProvider));
HttpClient httpClient;
if (this.useProxy != null || this.proxy != null)
{
var httpClientHandler = new HttpClientHandler();
if (this.useProxy != null)
{
httpClientHandler.UseProxy = this.useProxy.Value;
}
if (this.proxy != null)
{
httpClientHandler.Proxy = this.proxy;
}
httpClient = new HttpClient(httpClientHandler);
} else
{
httpClient = new HttpClient();
}
httpClient.BaseAddress = this.endpoint;
// Default use project scope api.
httpClient.DefaultRequestHeaders.Host = this.endpoint.Host;
if (this.timeout != null)
{
httpClient.Timeout = this.timeout.Value;
}
var client = new HttpLogServiceClient(httpClient, this.credentialProvider);
return client;
}
}
}

View File

@@ -0,0 +1,465 @@
//
// HttpRequestMessageBuilder.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using Aliyun.Api.LogService.Infrastructure.Authentication;
using Aliyun.Api.LogService.Utils;
using Google.Protobuf;
using Ionic.Zlib;
using LZ4;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace Aliyun.Api.LogService.Infrastructure.Protocol.Http
{
/// <summary>
/// Builder for constructing the <see cref="HttpRequestMessage"/>.
/// </summary>
/// <inheritdoc />
public class HttpRequestMessageBuilder : IRequestBuilder<HttpRequestMessage>
{
private static readonly Byte[] EmptyByteArray = new Byte[0];
private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
private readonly HttpRequestMessage httpRequestMessage;
private readonly Encoding encoding;
private readonly String path;
private readonly IDictionary<String, String> query;
/// <summary>
/// The authentication credential.
/// </summary>
private Credential credential;
/// <summary>
/// The real content to transfer.
/// </summary>
private Object content;
/// <summary>
/// The Content-MD5 header in HEX format.
/// </summary>
private String contentMd5Hex;
/// <summary>
/// Gets the serialized content.
/// </summary>
private Byte[] SerializedContent =>
this.content == null
? null
: this.content as Byte[]
?? throw new InvalidOperationException("Content must serialized before this operation.");
/// <summary>
/// Proceed the actions after content prepared (i.e., all transforms (e.g., serialize, compress, encrypt, encode) of <see cref="content"/> are applied).
/// </summary>
private Action contentHandler;
/// <summary>
/// The signature type.
/// </summary>
private SignatureType signatureType;
public HttpRequestMessageBuilder(HttpMethod method, String uri)
{
this.httpRequestMessage = new HttpRequestMessage(method, uri);
this.encoding = Encoding.UTF8;
ParseUri(uri, out this.path, out this.query);
this.FillDefaultHeaders();
}
private static void ParseUri(String uri, out String path, out IDictionary<String, String> query)
{
var absUri = new Uri(new Uri("http://fa.ke"), uri);
path = absUri.AbsolutePath;
query = absUri.ParseQueryString()
.ToEnumerable()
.ToDictionary(kv => kv.Key, kv => kv.Value); // NOTE: Restricted mode, key cannot be duplicated.
}
private void FillDefaultHeaders()
{
this.httpRequestMessage.Headers.Date = DateTimeOffset.Now;
this.httpRequestMessage.Headers.UserAgent.Add(new ProductInfoHeaderValue("log-dotnetcore-sdk", Constants.AssemblyVersion));
this.httpRequestMessage.Headers.Add(LogHeaders.ApiVersion, "0.6.0");
}
#region Query
public IRequestBuilder<HttpRequestMessage> Query(String key, String value)
{
this.query.Add(key, value);
return this;
}
public IRequestBuilder<HttpRequestMessage> Query(Object queryModel)
{
foreach (var kv in JObject.FromObject(queryModel, JsonSerializer.CreateDefault(JsonSerializerSettings)))
{
this.query.Add(kv.Key, kv.Value.Value<String>());
}
return this;
}
#endregion
#region Header
/// <summary>
/// Set headers of <see cref="T:System.Net.Http.Headers.HttpRequestHeaders" />
/// </summary>
/// <inheritdoc />
public IRequestBuilder<HttpRequestMessage> Header(String key, String value)
{
this.httpRequestMessage.Headers.Add(key, value);
return this;
}
private void ContentHeader(Action<HttpContentHeaders> option)
{
if (this.httpRequestMessage.Content == null)
{
this.contentHandler += () => option(this.httpRequestMessage.Content.Headers);
} else
{
option(this.httpRequestMessage.Content.Headers);
}
}
private void SetBodyRawSize(Int32 size)
=> this.httpRequestMessage.Headers.Add(LogHeaders.BodyRawSize, size.ToString());
private void SetCompressType(String compressType)
=> this.httpRequestMessage.Headers.Add(LogHeaders.CompressType, compressType);
private void SetSignatureMethod(String signatureMethod)
=> this.httpRequestMessage.Headers.Add(LogHeaders.SignatureMethod, signatureMethod);
#endregion
#region Content
public IRequestBuilder<HttpRequestMessage> Content(Byte[] content)
=> this.Content((Object) content);
public IRequestBuilder<HttpRequestMessage> Content(Object content)
{
this.content = content;
if (content is Byte[] data)
{
this.SetBodyRawSize(data.Length);
}
return this;
}
#endregion
#region Serialize
public IRequestBuilder<HttpRequestMessage> Serialize(SerializeType serializeType)
{
switch (this.content)
{
case null:
throw new InvalidOperationException("Nothing to serialize.");
case Byte[] _:
throw new InvalidOperationException("Content has already been serialized.");
}
switch (serializeType)
{
case SerializeType.Json:
{
this.ContentHeader(x => x.ContentType = new MediaTypeHeaderValue("application/json"));
var json = JsonConvert.SerializeObject(this.content, JsonSerializerSettings);
this.Content(this.encoding.GetBytes(json));
break;
}
case SerializeType.Protobuf:
{
if (!(this.content is IMessage protoMessage))
{
throw new ArgumentException("Serialization of ProtoBuf requires IMessage.");
}
this.ContentHeader(x => x.ContentType = new MediaTypeHeaderValue("application/x-protobuf"));
this.Content(protoMessage.ToByteArray());
break;
}
default:
{
throw new ArgumentOutOfRangeException(nameof(serializeType), serializeType, null);
}
}
return this;
}
#endregion Serialize
#region Compress
public IRequestBuilder<HttpRequestMessage> Compress(CompressType compressType)
{
if (this.SerializedContent == null)
{
throw new InvalidOperationException("Nothing to compress.");
}
switch (compressType)
{
case CompressType.None:
{
break;
}
case CompressType.Lz4:
{
this.SetCompressType("lz4");
this.content = LZ4Codec.Encode(this.SerializedContent, 0, this.SerializedContent.Length);
break;
}
case CompressType.Deflate:
{
this.SetCompressType("deflate");
this.content = ZlibStream.CompressBuffer(this.SerializedContent);
break;
}
default:
{
throw new ArgumentOutOfRangeException(nameof(compressType), compressType, null);
}
}
return this;
}
#endregion Compress
#region Authentication
public IRequestBuilder<HttpRequestMessage> Authenticate(Credential credential)
{
Ensure.NotNull(credential, nameof(credential));
Ensure.NotEmpty(credential.AccessKeyId, nameof(credential.AccessKeyId));
Ensure.NotEmpty(credential.AccessKey, nameof(credential.AccessKey));
this.credential = credential;
return this;
}
#endregion
#region Sign
public IRequestBuilder<HttpRequestMessage> Sign(SignatureType signatureType)
{
this.signatureType = signatureType;
return this;
}
private Byte[] ComputeSignature()
{
switch (this.signatureType)
{
case SignatureType.HmacSha1:
{
using (var hasher = new HMACSHA1(this.encoding.GetBytes(this.credential.AccessKey)))
{
this.SetSignatureMethod("hmac-sha1"); // This header must be set before generating sign source.
var signSource = this.GenerateSignSource();
var sign = hasher.ComputeHash(this.encoding.GetBytes(signSource));
return sign;
}
}
default:
{
throw new ArgumentOutOfRangeException(nameof(this.signatureType), this.signatureType, "Currently only support [hmac-sha1] signature.");
}
}
}
private String GenerateSignSource()
{
var verb = this.httpRequestMessage.Method.Method;
var contentMd5 = this.contentMd5Hex;
var contentType = this.httpRequestMessage.Content?.Headers.ContentType.MediaType;
var date = this.httpRequestMessage.Headers.Date?.ToString("r"); /* RFC 822 format */
var logHeaders = String.Join("\n", this.httpRequestMessage.Headers
.Concat(this.httpRequestMessage.Content?.Headers ?? Enumerable.Empty<KeyValuePair<String, IEnumerable<String>>>())
.Where(x => x.Key.StartsWith("x-log") || x.Key.StartsWith("x-acs"))
.Select(x => new KeyValuePair<String, String>(x.Key.ToLower(), x.Value.SingleOrDefault() /* Fault tolerance */))
.Where(x => x.Value.IsNotEmpty()) // Remove empty header
.OrderBy(x => x.Key)
.Select(x => $"{x.Key}:{x.Value}"));
var resource = this.httpRequestMessage.RequestUri.OriginalString;
String signSource;
if (this.query.IsEmpty())
{
signSource = String.Join("\n", verb, contentMd5 ?? String.Empty, contentType ?? String.Empty, date, logHeaders, resource);
} else
{
signSource = String.Join("\n", verb, contentMd5 ?? String.Empty, contentType ?? String.Empty, date, logHeaders, resource) + "?" +
String.Join("&", this.query
.OrderBy(x => x.Key)
.Select(x => $"{x.Key}={x.Value}"));
}
return signSource;
}
private Byte[] CalculateContentMd5()
{
using (var hasher = MD5.Create())
{
return hasher.ComputeHash(this.SerializedContent);
}
}
#endregion Signature
public HttpRequestMessage Build()
{
// Validate
Ensure.NotNull(this.credential, nameof(this.credential));
Ensure.NotEmpty(this.credential.AccessKeyId, nameof(this.credential.AccessKeyId));
Ensure.NotEmpty(this.credential.AccessKey, nameof(this.credential.AccessKey));
// Process sts-token.
var hasSecurityToken = this.httpRequestMessage.Headers.TryGetValues(LogHeaders.SecurityToken, out var securityTokens)
&& securityTokens.FirstOrDefault().IsNotEmpty();
if (!hasSecurityToken && this.credential.StsToken.IsNotEmpty())
{
this.httpRequestMessage.Headers.Add(LogHeaders.SecurityToken, this.credential.StsToken);
}
// NOTE: If x-log-bodyrawsize is empty, fill it with "0". Otherwise, some method call will be corrupted.
if (!this.httpRequestMessage.Headers.Contains(LogHeaders.BodyRawSize))
{
this.SetBodyRawSize(0);
}
// Build content if necessary
if (this.SerializedContent.IsNotEmpty())
{
this.httpRequestMessage.Content = new ByteArrayContent(this.SerializedContent);
this.contentHandler?.Invoke();
// Prepare header
this.ContentHeader(x =>
{
// Compute actual length
x.ContentLength = this.SerializedContent.Length;
// Compute actual MD5
this.contentMd5Hex = BitConverter.ToString(this.CalculateContentMd5()).Replace("-", String.Empty);
x.Add("Content-MD5", this.contentMd5Hex); // Non-standard header
});
} else if (this.httpRequestMessage.Method == HttpMethod.Post || this.httpRequestMessage.Method == HttpMethod.Put)
{
// When content is empty as well as method is `POST` or `PUT`, generate an empty content and corresponding headers.
this.httpRequestMessage.Content = new ByteArrayContent(EmptyByteArray);
// Don't invoke `contentHandler` here!
/*
* NOTE:
* Here is a annoying hack, the log service service cannot accept empty `Content-Type`
* header when POST or PUT methods. So, we have to force set some header value.
*/
this.ContentHeader(x =>
{
x.ContentType = new MediaTypeHeaderValue("application/json");
// For some reason, I think it is better to set `Content-Type` to `0` to prevent
// some unexpected behavior on server side.
x.ContentLength = 0;
});
}
// Do signature
var signature = Convert.ToBase64String(this.ComputeSignature());
this.httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("LOG", $"{this.credential.AccessKeyId}:{signature}");
// Rebuild the RequestUri
var queryString = String.Join("&", this.query
.OrderBy(x => x.Key)
.Select(x => $"{encodeUrl(x.Key)}={encodeUrl(x.Value)}"));
var pathAndQuery = queryString.IsNotEmpty() ? $"{this.path}?{queryString}" : this.path;
this.httpRequestMessage.RequestUri = new Uri(pathAndQuery, UriKind.Relative);
return this.httpRequestMessage;
}
private String encodeUrl(String value)
{
if (value == null)
{
return "";
}
string encoded = HttpUtility.UrlEncode(value, this.encoding);
return encoded.Replace("+", "%20").Replace("*", "%2A").Replace("~", "%7E").Replace("/", "%2F");
}
}
}

View File

@@ -0,0 +1,126 @@
//
// HttpResponse.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Aliyun.Api.LogService.Domain;
namespace Aliyun.Api.LogService.Infrastructure.Protocol.Http
{
/// <summary>
/// 服务响应包装对象,包含未反序列化的原始数据,可通过 <c>ReadXxxAsync()</c> 方法读取原始报文。
/// </summary>
public class HttpResponse : IResponse
{
internal HttpResponseMessage ResponseMessage { get; }
public Boolean IsSuccess { get; }
public HttpStatusCode StatusCode { get; }
public String RequestId { get; }
public IDictionary<String, String> Headers { get; }
public Error Error { get; }
public HttpResponse(HttpResponseMessage responseMessage, Boolean isSuccess, HttpStatusCode statusCode, String requestId, IDictionary<String, String> headers, Error error)
{
this.ResponseMessage = responseMessage;
this.IsSuccess = isSuccess;
this.StatusCode = statusCode;
this.RequestId = requestId;
this.Headers = headers;
this.Error = error;
}
public IResponse EnsureSuccess()
{
if (!this.IsSuccess)
{
throw this.Error == null
? new LogServiceException(this.RequestId, ErrorCode.SdkInternalError, "The error detail result is missing.")
: new LogServiceException(this.RequestId, this.Error.ErrorCode, this.Error.ErrorMessage);
}
return this;
}
public Task<TResult> ReadAsAsync<TResult>()
{
return this.ResponseMessage.Content.ReadAsAsync<TResult>();
}
public Task<Stream> ReadAsByteStreamAsync()
{
return this.ResponseMessage.Content.ReadAsStreamAsync();
}
public Task<Byte[]> ReadAsByteArrayAsync()
{
return this.ResponseMessage.Content.ReadAsByteArrayAsync();
}
public override String ToString()
=> $"[{this.RequestId}] {this.StatusCode}{(this.IsSuccess ? String.Empty : " Error:" + this.Error)}";
}
/// <summary>
/// 服务响应包装对象,此类型包含一个已反序列化为 <typeparamref name="TResult" /> 的 <see cref="Result">结果对象</see>。
/// </summary>
/// <typeparam name="TResult">响应包含结果的类型。</typeparam>
public class HttpResponse<TResult> : HttpResponse, IResponse<TResult>
where TResult : class
{
public TResult Result { get; }
public HttpResponse(HttpResponseMessage responseMessage, Boolean isSuccess, HttpStatusCode statusCode, String requestId, IDictionary<String, String> headers, Error error)
: base(responseMessage, isSuccess, statusCode, requestId, headers, error)
{
this.Result = null;
}
public HttpResponse(HttpResponseMessage responseMessage, Boolean isSuccess, HttpStatusCode statusCode, String requestId, IDictionary<String, String> headers, TResult result)
: base(responseMessage, isSuccess, statusCode, requestId, headers, null)
{
this.Result = result;
}
IResponse<TResult> IResponse<TResult>.EnsureSuccess()
{
this.EnsureSuccess();
return this;
}
public override String ToString()
=> base.ToString() + $" Result:{(this.Result == null ? "<null>" : this.Result.GetType().FullName)}";
}
}

View File

@@ -0,0 +1,85 @@
//
// HttpResponseExtensions.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
namespace Aliyun.Api.LogService.Infrastructure.Protocol.Http
{
public static class HttpResponseExtensions
{
private static HttpResponse ToHttpResponse(this IResponse response)
=> response is HttpResponse httpResponse
? httpResponse
: throw new ArgumentException($"response must be [{nameof(HttpResponse)}].", nameof(response));
private static HttpResponse<T> ToHttpResponse<T>(this IResponse<T> response)
where T : class
=> response is HttpResponse<T> httpResponse
? httpResponse
: throw new ArgumentException($"response must be [{nameof(HttpResponse)}].", nameof(response));
/// <summary>
/// 获取此响应对象对应底层的 <see cref="HttpResponseMessage"/> 。
/// </summary>
/// <param name="response">响应对象。</param>
/// <returns>底层的 <see cref="HttpResponseMessage"/> 。</returns>
public static HttpResponseMessage GetHttpResponseMessage(this IResponse response)
{
return response.ToHttpResponse().ResponseMessage;
}
/// <summary>
/// 获取此响应对象对应的 HTTP 响应码。
/// </summary>
/// <param name="response">响应对象。</param>
/// <returns>HTTP 响应码。</returns>
public static HttpStatusCode GetHttpStatusCode(this IResponse response)
{
return response.ToHttpResponse().StatusCode;
}
/// <summary>
/// </summary>
/// <param name="source">带有结果对象类型的响应消息解释器。</param>
/// <param name="transformer">结果转换器。</param>
/// <typeparam name="TSource">转换前结果对象类型。</typeparam>
/// <typeparam name="TResult">转换后结果对象类型。</typeparam>
/// <returns>异步解释结果。</returns>
public static IResponse<TResult> Transform<TSource, TResult>(this IResponse<TSource> source,
Func<IDictionary<String, String>, TSource, TResult> transformer)
where TSource : class
where TResult : class
{
var httpResponse = source.ToHttpResponse();
var result = transformer(source.Headers, source.Result);
var response = new HttpResponse<TResult>(httpResponse.ResponseMessage, httpResponse.IsSuccess, httpResponse.StatusCode, httpResponse.RequestId, httpResponse.Headers, result);
return response;
}
}
}

View File

@@ -0,0 +1,327 @@
//
// HttpResponseMessageResolver.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Aliyun.Api.LogService.Utils;
using Ionic.Zlib;
using LZ4;
using Newtonsoft.Json;
namespace Aliyun.Api.LogService.Infrastructure.Protocol.Http
{
public class HttpResponseMessageResolver : IResponseResolver
{
public HttpResponseMessage HttpResponseMessage { get; }
public String RequestId { get; private set; }
public Boolean IsSuccess { get; private set; }
public HttpStatusCode StatusCode { get; private set; }
public IDictionary<String, String> Headers { get; private set; }
private Func<Byte[], Byte[]> decompressor;
private Func<Byte[], Type, Object> deserializer;
public HttpResponseMessageResolver(HttpResponseMessage httpResponseMessage)
{
this.HttpResponseMessage = httpResponseMessage;
this.decompressor = this.AutoDecompressContent;
this.deserializer = this.AutoDeserializeContent;
}
public static IResponseResolver For(HttpResponseMessage httpResponseMessage)
{
return new HttpResponseMessageResolver(httpResponseMessage);
}
public static IResponseResolver<TResult> For<TResult>(HttpResponseMessage httpResponseMessage)
where TResult : class
{
return new HttpResponseMessageResolver(httpResponseMessage).With<TResult>();
}
public IResponseResolver<TResult> With<TResult>()
where TResult : class
{
return new TypedWrapper<TResult>(this);
}
public IResponseResolver Decompress(Func<Byte[], Byte[]> decompressor)
{
this.decompressor = decompressor ?? throw new ArgumentNullException(nameof(decompressor));
return this;
}
public IResponseResolver<TResult> Deserialize<TResult>(Func<Byte[], TResult> deserializer) where TResult : class
{
if (deserializer == null)
{
throw new ArgumentNullException(nameof(deserializer));
}
this.deserializer = (data, resultType) =>
{
var bindType = typeof(TResult);
if (bindType != resultType)
{
throw new ArgumentException($"Type mismatch, binding type: [{bindType}], actual type: [{resultType}]", nameof(TResult));
}
return deserializer(data);
};
return new TypedWrapper<TResult>(this);
}
#region Decompress
private Byte[] AutoDecompressContent(Byte[] data)
{
// Try decompress data if necessary
if (this.TryGetCompressTypeHeader(out var compressType))
{
var optionalBodyRawSize = this.GetOptionalBodyRawSizeHeader();
// Replace the data
return DecompressContent(compressType, data, optionalBodyRawSize);
}
return data;
}
private Boolean TryGetCompressTypeHeader(out CompressType compressType)
{
if (!this.HttpResponseMessage.Headers.TryGetValues(LogHeaders.CompressType, out var compressTypes))
{
// No header
compressType = CompressType.None;
return false;
}
var compressTypeValue = compressTypes.FirstOrDefault(); // Fault tolerance (TODO: Show warns about duplicated keys)
if (compressTypeValue.IsEmpty())
{
// Header is empty
compressType = CompressType.None;
return false;
}
// Convert value to enum
return Enum.TryParse(compressTypeValue, true, out compressType)
? true
: throw new ArgumentException($"Compress type [{compressTypeValue}] is not supported.", LogHeaders.CompressType);
}
private Int32? GetOptionalBodyRawSizeHeader()
{
if (!this.HttpResponseMessage.Headers.TryGetValues(LogHeaders.BodyRawSize, out var bodyRawSizes))
{
// No header
return null;
}
var bodyRawSizeValue = bodyRawSizes.FirstOrDefault(); // Fault tolerance (TODO: Show warns about duplicated keys)
if (bodyRawSizeValue.IsEmpty())
{
// Header is empty
return null;
}
return Int32.Parse(bodyRawSizeValue); // Let exception raise when format is incorrect.
}
private static Byte[] DecompressContent(CompressType compressType, Byte[] orignData, Int32? rawSize)
{
switch (compressType)
{
case CompressType.None:
{
return orignData;
}
case CompressType.Lz4:
{
if (!rawSize.HasValue)
{
throw new ArgumentException($"{LogHeaders.BodyRawSize} is required when using [lz4] compress.");
}
var rawData = LZ4Codec.Decode(orignData, 0, orignData.Length, rawSize.Value);
return rawData;
}
case CompressType.Deflate:
{
var rawData = ZlibStream.UncompressBuffer(orignData);
return rawData;
}
default:
{
throw new ArgumentOutOfRangeException(nameof(compressType), compressType, null);
}
}
}
#endregion Decompress
#region Deserialize
private Object AutoDeserializeContent(Byte[] data, Type resultType)
{
// Content negotiate is not supported.
using (var stream = new MemoryStream(data, false))
using (var textReader = new StreamReader(stream, Encoding.UTF8 /*TODO: Hard code*/))
{
return JsonSerializer.CreateDefault().Deserialize(textReader, resultType);
}
}
#endregion
private void ResolveInternal()
{
if (this.HttpResponseMessage.Headers.TryGetValues(LogHeaders.RequestId, out var requestIds))
{
this.RequestId = requestIds.FirstOrDefault(); // Fault tolerance.
}
this.IsSuccess = this.HttpResponseMessage.IsSuccessStatusCode;
this.StatusCode = this.HttpResponseMessage.StatusCode;
this.Headers = this.HttpResponseMessage.Headers
.Concat(this.HttpResponseMessage.Content.Headers ?? Enumerable.Empty<KeyValuePair<String, IEnumerable<String>>>())
.ToDictionary(kv => kv.Key, kv => kv.Value.FirstOrDefault() /* Fault tolerance */);
}
private async Task<TResult> ResolveResultAsync<TResult>()
where TResult : class
{
var httpContent = this.HttpResponseMessage.Content;
if (httpContent == null)
{
return null;
}
var data = await httpContent.ReadAsByteArrayAsync();
if (data.IsEmpty())
{
return null;
}
data = this.decompressor(data);
var result = this.deserializer(data, typeof(TResult));
return (TResult) result; // Always safe! Expect the custom serializer does some weird operations.
}
public async Task<IResponse> ResolveAsync()
{
this.ResolveInternal();
var readOnlyHeaders = new ReadOnlyDictionary<String, String>(this.Headers);
var error = this.IsSuccess ? null : await this.HttpResponseMessage.Content.ReadAsAsync<Error>();
return new HttpResponse(this.HttpResponseMessage, this.IsSuccess, this.StatusCode, this.RequestId, readOnlyHeaders, error);
}
public async Task<IResponse<TResult>> ResolveAsync<TResult>() where TResult : class
{
this.ResolveInternal();
var readOnlyHeaders = new ReadOnlyDictionary<String, String>(this.Headers);
if (!this.IsSuccess)
{
var error = await this.HttpResponseMessage.Content.ReadAsAsync<Error>();
return new HttpResponse<TResult>(this.HttpResponseMessage, this.IsSuccess, this.StatusCode, this.RequestId, readOnlyHeaders, error);
}
var result = await this.ResolveResultAsync<TResult>();
return new HttpResponse<TResult>(this.HttpResponseMessage, this.IsSuccess, this.StatusCode, this.RequestId, readOnlyHeaders, result);
}
private class TypedWrapper<TResult> : IResponseResolver<TResult>
where TResult : class
{
private readonly HttpResponseMessageResolver innerResolver;
internal TypedWrapper(HttpResponseMessageResolver innerResolver)
{
this.innerResolver = innerResolver;
}
public IResponseResolver<TResult> Decompress(Func<Byte[], Byte[]> decompressor)
{
this.innerResolver.Decompress(decompressor);
return this;
}
public IResponseResolver<TResult> Deserialize(Func<Byte[], TResult> deserializer)
{
this.innerResolver.Deserialize(deserializer);
return this;
}
public Task<IResponse<TResult>> ResolveAsync()
{
return this.innerResolver.ResolveAsync<TResult>();
}
public async Task<IResponse<TNewResult>> ResolveAsync<TNewResult>(Func<TResult, TNewResult> transformer)
where TNewResult : class
{
this.innerResolver.ResolveInternal();
var readOnlyHeaders = new ReadOnlyDictionary<String, String>(this.innerResolver.Headers);
if (!this.innerResolver.IsSuccess)
{
var error = await this.innerResolver.HttpResponseMessage.Content.ReadAsAsync<Error>();
return new HttpResponse<TNewResult>(this.innerResolver.HttpResponseMessage, this.innerResolver.IsSuccess, this.innerResolver.StatusCode, this.innerResolver.RequestId, readOnlyHeaders, error);
}
var result = await this.innerResolver.ResolveResultAsync<TResult>();
var newResult = transformer(result);
return new HttpResponse<TNewResult>(this.innerResolver.HttpResponseMessage, this.innerResolver.IsSuccess, this.innerResolver.StatusCode, this.innerResolver.RequestId, readOnlyHeaders, newResult);
}
}
}
}

View File

@@ -0,0 +1,225 @@
//
// LogServiceClientBuilders.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using Aliyun.Api.LogService.Domain.Log;
using Aliyun.Api.LogService.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Aliyun.Api.LogService.Infrastructure.Protocol.Http
{
public static class LogHeaderExtensions
{
private static T? ParseNullable<T>(this String source, Func<String, T> parse) where T : struct
{
if (source.IsEmpty())
{
return null;
}
return parse(source);
}
private static T ParseNotNull<T>(this String source, Func<String, T> parse)
{
return parse(source);
}
#region PullLogs
/// <summary>
/// 获取下一条数据的cursor。
/// </summary>
/// <param name="response"><c>PullLogs</c> 的响应消息。</param>
/// <returns>下一条数据的cursor。</returns>
public static String GetLogCursor(this IResponse<PullLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.Cursor);
/// <summary>
/// 获取当前返回数量。
/// </summary>
/// <param name="response"><c>PullLogs</c> 的响应消息。</param>
/// <returns>当前返回数量。</returns>
/// <exception cref="FormatException">Header的值不是整数形式。</exception>
public static Int64 GetLogCount(this IResponse<PullLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.Count)
.ParseNotNull(Int64.Parse);
/// <summary>
/// 获取报文压缩类型(可空)。
/// </summary>
/// <param name="response"><c>PullLogs</c> 的响应消息。</param>
/// <returns>报文压缩类型(可空)。</returns>
/// <exception cref="OverflowException">Header的值在当前SDK版本不支持。</exception>
/// <seealso cref="CompressType"/>
public static CompressType? GetLogCompressType(this IResponse<PullLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.CompressType)
.ParseNullable(x => (CompressType) Enum.Parse(typeof(CompressType), x, true));
/// <summary>
/// 获取响应消息中 Body 的原始大小。
/// </summary>
/// <param name="response"><c>PullLogs</c> 的响应消息。</param>
/// <returns>响应消息中 Body 的原始大小。</returns>
/// <exception cref="FormatException">当Header的值不是整数形式。</exception>
public static Int64 GetLogBodyRawSize(this IResponse<PullLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.BodyRawSize)
.ParseNotNull(Int64.Parse);
#endregion
#region GetLogs
/// <summary>
/// 获取查询结果的状态。
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns>获取查询结果的状态。</returns>
/// <exception cref="OverflowException">Header的值在当前SDK版本不支持。</exception>
/// <seealso cref="LogProgressState"/>
public static LogProgressState GetLogProgress(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.Progress)
.ParseNotNull(x => (LogProgressState) Enum.Parse(typeof(LogProgressState), x, true));
/// <summary>
/// 获取当前返回数量。
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns>当前返回数量。</returns>
/// <exception cref="FormatException">Header的值不是整数形式。</exception>
public static Int64 GetLogCount(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.Count)
.ParseNotNull(Int64.Parse);
/// <summary>
/// TODO: 暂无文档)
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns></returns>
/// <exception cref="FormatException">Header的值不是整数形式。</exception>
public static Int64 GetLogProcessedRows(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.ProcessedRows)
.ParseNotNull(Int64.Parse);
/// <summary>
/// TODO: 暂无文档)
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns></returns>
/// <exception cref="FormatException">Header的值不是整数形式。</exception>
public static Int64 GetLogElapsedMillisecond(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.ElapsedMillisecond)
.ParseNotNull(Int64.Parse);
/// <summary>
/// TODO: 暂无文档)
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns></returns>
public static LogQueryInfo GetLogQueryInfo(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.QueryInfo)
.ParseNotNull(JsonConvert.DeserializeObject<LogQueryInfo>);
/// <summary>
/// TODO: 暂无文档)
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns></returns>
/// <exception cref="FormatException">Header的值不是JSON对象形式。</exception>
public static dynamic GetLogQueryInfoAsDynamic(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.QueryInfo)
.ParseNotNull(x =>
{
if (x.IsEmpty())
{
return new JObject();
}
try
{
return JObject.Parse(x);
} catch (JsonReaderException e)
{
// Prevent underlying type expose explicitly.
throw new FormatException(e.Message, e);
}
});
/// <summary>
/// TODO: 暂无文档)
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns></returns>
public static Boolean GetLogHasSql(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.HasSql)
.ParseNotNull(Boolean.Parse);
/// <summary>
/// TODO: 暂无文档)
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns></returns>
public static String GetLogAggQuery(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.AggQuery);
/// <summary>
/// TODO: 暂无文档)
/// </summary>
/// <param name="response"><c>GetLogs</c> 的响应消息。</param>
/// <returns></returns>
public static String GetLogWhereQuery(this IResponse<GetLogsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.WhereQuery);
#endregion
#region GetHistograms
/// <summary>
/// 获取当前返回数量。
/// </summary>
/// <param name="response"><c>GetLogHistograms</c> 的响应消息。</param>
/// <returns>当前返回数量。</returns>
/// <exception cref="FormatException">Header的值不是整数形式。</exception>
public static Int64 GetLogCount(this IResponse<GetLogHistogramsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.Count)
.ParseNotNull(Int64.Parse);
/// <summary>
/// 获取查询结果的状态。
/// </summary>
/// <param name="response"><c>GetLogHistograms</c> 的响应消息。</param>
/// <returns>获取查询结果的状态。</returns>
/// <exception cref="OverflowException">Header的值在当前SDK版本不支持。</exception>
/// <seealso cref="LogProgressState"/>
public static LogProgressState GetLogProgress(this IResponse<GetLogHistogramsResult> response)
=> response.Headers.GetValueOrDefault(LogHeaders.Progress)
.ParseNotNull(x => (LogProgressState) Enum.Parse(typeof(LogProgressState), x, true));
#endregion
}
}

View File

@@ -0,0 +1,110 @@
//
// LogHeaders.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Aliyun.Api.LogService.Domain.Log;
namespace Aliyun.Api.LogService.Infrastructure.Protocol.Http
{
/// <summary>
/// 日志服务扩展Header。
/// </summary>
public static class LogHeaders
{
/// <summary>
/// API 的版本号。
/// </summary>
public static readonly String ApiVersion = $"x-log-{nameof(ApiVersion).ToLower()}";
/// <summary>
/// 请求的 Body 原始大小。
/// 当无 Body 时,该字段为 0
/// 当 Body 是压缩数据,则为压缩前的原始数据大小。
/// 该域取值范围为 0 ~ 3 * 1024 * 1024。
/// 该字段为非必选字段,只在压缩时需要。
/// </summary>
public static readonly String BodyRawSize = $"x-log-{nameof(BodyRawSize).ToLower()}";
/// <summary>
/// API 请求中 Body 部分使用的压缩方式。
/// 如果不压缩可以不提供该请求头。
/// </summary>
/// <seealso cref="CompressType"/>
public static readonly String CompressType = $"x-log-{nameof(CompressType).ToLower()}";
/// <summary>
/// 当前发送时刻的时间,格式和 Date 头一致。
/// 该请求头为可选项。如果请求中包含该公共请求头,它的值会取代 Date 标准头的值用于服务端请求验证(该字段不参与签名)。
/// 无论是否有 x-log-date 头HTTP 标准 Date 头都必须提供。
/// </summary>
public static readonly String LogDate = $"x-log-{nameof(LogDate).ToLower()}";
/// <summary>
/// 签名计算方式。
/// </summary>
/// <seealso cref="SignatureType"/>
public static readonly String SignatureMethod = $"x-log-{nameof(SignatureMethod).ToLower()}";
/// <summary>
/// 使用 STS 临时身份发送数据。当使用 STS 临时身份时必填,其他情况不要填写。
/// </summary>
public static readonly String SecurityToken = "x-acs-security-token";
/// <summary>
/// 服务端产生的标示该请求的唯一 ID。该响应头与具体应用无关主要用于跟踪和调查问题。
/// 如果用户希望调查出现问题的 API 请求,可以向 Log Service 团队提供该 ID。
/// </summary>
public static readonly String RequestId = $"x-log-{nameof(RequestId).ToLower()}";
/// <summary>
/// 日志上传的hash key用来判断上传日志应该落在哪个 shard 中。
/// </summary>
public static readonly String HashKey = $"x-log-{nameof(HashKey).ToLower()}";
/// <summary>
/// 当前返回数量。
/// </summary>
public static readonly String Count = $"x-log-{nameof(Count).ToLower()}";
/// <summary>
/// 当前读取数据下一条 cursor。
/// </summary>
public static readonly String Cursor = $"x-log-{nameof(Cursor).ToLower()}";
/// <summary>
/// 查询结果的状态,表示本次是否完整。
/// </summary>
/// <seealso cref="LogProgressState"/>
public static readonly String Progress = "x-log-progress";
public static readonly String AggQuery = "x-log-agg-query";
public static readonly String ElapsedMillisecond = "x-log-elapsed-millisecond";
public static readonly String HasSql = "x-log-has-sql";
public static readonly String ProcessedRows = "x-log-processed-rows";
public static readonly String QueryInfo = "x-log-query-info";
public static readonly String WhereQuery = "x-log-where-query";
}
}

View File

@@ -0,0 +1,115 @@
//
// IRequestBuilder.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Net.Http;
using Aliyun.Api.LogService.Infrastructure.Authentication;
namespace Aliyun.Api.LogService.Infrastructure.Protocol
{
/// <summary>
/// The builder for constructing request <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of building request.</typeparam>
public interface IRequestBuilder<out T>
{
/// <summary>
/// Adds query of request.
/// </summary>
/// <param name="key">The key of query.</param>
/// <param name="value">The value of query.</param>
/// <returns>This builder.</returns>
/// <exception cref="ArgumentException"><paramref name="key"/> has already been exist.</exception>
IRequestBuilder<T> Query(String key, String value);
/// <summary>
/// Add all public gettable properties of <paramref name="queryModel"/> to query.
/// </summary>
/// <param name="queryModel">A simple data object with no nested complex properties.</param>
/// <returns>This builder.</returns>
/// <exception cref="InvalidCastException">If <paramref name="queryModel"/> has nested complex properties.</exception>
IRequestBuilder<T> Query(Object queryModel);
/// <summary>
/// Adds header of request.
/// </summary>
/// <param name="key">The key of header.</param>
/// <param name="value">The value of header.</param>
/// <returns>This builder.</returns>
IRequestBuilder<T> Header(String key, String value);
/// <summary>
/// Sets serialized content of request.
/// </summary>
/// <param name="content">The serialized content.</param>
/// <returns>This builder.</returns>
/// <seealso cref="Content(Object)"/>
IRequestBuilder<T> Content(Byte[] content);
/// <summary>
/// Sets content of request.
/// </summary>
/// <param name="content">The content, can be serialized or not.</param>
/// <returns>This builder.</returns>
IRequestBuilder<T> Content(Object content);
/// <summary>
/// Serialize the content.
/// </summary>
/// <param name="serializeType">The serialze type</param>
/// <returns>This builder.</returns>
/// <exception cref="InvalidOperationException">If nothing to serialize, or content has already been serialized.</exception>
IRequestBuilder<T> Serialize(SerializeType serializeType);
/// <summary>
/// Compress the content.
/// </summary>
/// <param name="compressType">The compress type</param>
/// <returns>This builder.</returns>
/// <exception cref="InvalidOperationException">If nothing to compress, or content is not serialized.</exception>
IRequestBuilder<T> Compress(CompressType compressType);
/// <summary>
/// Set credential to authenticate.
/// </summary>
/// <param name="credential">The authenticate credential.</param>
/// <returns></returns>
IRequestBuilder<HttpRequestMessage> Authenticate(Credential credential);
/// <summary>
/// Specify the signature type and credentials to sign.
/// </summary>
/// <param name="signatureType">The signature type</param>
/// <returns>This builder.</returns>
IRequestBuilder<T> Sign(SignatureType signatureType);
/// <summary>
/// Build the request <typeparamref name="T"/>.
/// </summary>
/// <returns>The built request.</returns>
T Build();
}
}

View File

@@ -0,0 +1,110 @@
//
// IResponse.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Mime;
using System.Threading.Tasks;
using Aliyun.Api.LogService.Domain;
namespace Aliyun.Api.LogService.Infrastructure.Protocol
{
/// <summary>
/// 服务响应包装对象,包含未反序列化的原始数据,可通过 <c>ReadXxxAsync()</c> 方法读取原始报文。
/// </summary>
public interface IResponse
{
/// <summary>
/// 当前响应是否为一个成功的响应。
/// </summary>
Boolean IsSuccess { get; }
/// <summary>
/// 服务端产生的标示该请求的唯一 ID。
/// 该响应头与具体应用无关,主要用于跟踪和调查问题。
/// 如果用户希望调查出现问题的 API 请求,可以向 Log Service 团队提供该 ID。
/// </summary>
String RequestId { get; }
/// <summary>
/// 当前响应的元数据。
/// </summary>
IDictionary<String, String> Headers { get; }
/// <summary>
/// 当前响应包含的错误信息,在<see cref="IsSuccess"/>为<c>false</c>时存在。
/// </summary>
Error Error { get; }
/// <summary>
/// 确保当前响应是成功的,否则将抛出包含错误码及错误消息的 <see cref="LogServiceException"/> 。
/// </summary>
/// <returns>当前响应实例。</returns>
/// <exception cref="LogServiceException">当前响应的 <see cref="IsSuccess"/> 不为<c>true</c></exception>
IResponse EnsureSuccess();
/// <summary>
/// 读取原始数据并反序列化为 <typeparamref name="TResult"/> 。
/// 反序列化过程会根据<see cref="ContentType"/>确定原始数据类型。
/// </summary>
/// <typeparam name="TResult">反序列化结果的类型。</typeparam>
/// <returns>反序列化对象异步结果。</returns>
Task<TResult> ReadAsAsync<TResult>();
/// <summary>
/// 读取原始数据并且作为字节流的形式返回。
/// </summary>
/// <returns>异步字节数据流。</returns>
Task<Stream> ReadAsByteStreamAsync();
/// <summary>
/// 读取原始数据并且作为字节数组的形式返回。
/// </summary>
/// <returns>异步字节数组。</returns>
Task<Byte[]> ReadAsByteArrayAsync();
}
/// <summary>
/// 服务响应包装对象,此类型包含一个已反序列化为 <typeparamref name="TResult" /> 的 <see cref="Result">结果对象</see>。
/// </summary>
/// <typeparam name="TResult">响应包含结果的类型。</typeparam>
public interface IResponse<out TResult> : IResponse
where TResult : class
{
/// <summary>
/// 已反序列化的结果对象,在<see cref="IResponse.IsSuccess"/>为<c>true</c>时存在。
/// </summary>
TResult Result { get; }
/// <summary>
/// 确保当前响应是成功的,否则将抛出包含错误码及错误消息的 <see cref="LogServiceException"/> 。
/// </summary>
/// <returns>当前响应实例。</returns>
/// <exception cref="LogServiceException">当前响应的 <see cref="IResponse.IsSuccess"/> 不为<c>true</c></exception>
new IResponse<TResult> EnsureSuccess();
}
}

View File

@@ -0,0 +1,113 @@
//
// IResponseResolver.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading.Tasks;
namespace Aliyun.Api.LogService.Infrastructure.Protocol
{
/// <summary>
/// 响应消息解释器。
/// </summary>
public interface IResponseResolver
{
/// <summary>
/// 使用 <typeparamref name="TResult"/> 作为目标对象类型。
/// </summary>
/// <typeparam name="TResult">目标对象类型</typeparam>
/// <returns>带有结果对象类型的响应消息解释器。</returns>
IResponseResolver<TResult> With<TResult>()
where TResult : class;
/// <summary>
/// 设置解压缩原始数据的处理器,此操作会使默认解压缩处理器失效。
/// </summary>
/// <param name="decompressor">解压缩处理器。</param>
/// <returns>当前解释器。</returns>
IResponseResolver Decompress(Func<Byte[], Byte[]> decompressor);
/// <summary>
/// 设置反序列化原始数据的处理器,此操作会使默认反序列化处理器失效。
/// </summary>
/// <param name="deserializer">反序列化处理器。</param>
/// <typeparam name="TResult">结果对象类型。</typeparam>
/// <returns>带有结果对象类型的响应消息解释器。</returns>
IResponseResolver<TResult> Deserialize<TResult>(Func<Byte[], TResult> deserializer)
where TResult : class;
/// <summary>
/// 解释响应消息。
/// </summary>
/// <returns>异步解释结果。</returns>
Task<IResponse> ResolveAsync();
/// <summary>
/// 解释响应消息,并反序列化为 <typeparamref name="TResult"/> 。
/// </summary>
/// <typeparam name="TResult">结果对象类型。</typeparam>
/// <returns>异步解释结果。</returns>
Task<IResponse<TResult>> ResolveAsync<TResult>()
where TResult : class;
}
/// <summary>
/// 带有结果对象类型的响应消息解释器。
/// </summary>
/// <typeparam name="TResult">结果对象类型。</typeparam>
public interface IResponseResolver<TResult>
where TResult : class
{
/// <summary>
/// 设置解压缩原始数据的处理器,此操作会使默认解压缩处理器失效。
/// </summary>
/// <param name="decompressor">解压缩处理器。</param>
/// <returns>当前解释器。</returns>
IResponseResolver<TResult> Decompress(Func<Byte[], Byte[]> decompressor);
/// <summary>
/// 设置反序列化原始数据的处理器,此操作会使默认反序列化处理器失效。
/// </summary>
/// <param name="deserializer">反序列化处理器。</param>
/// <returns>当前解释器。</returns>
IResponseResolver<TResult> Deserialize(Func<Byte[], TResult> deserializer);
/// <summary>
/// 解释响应消息,并反序列化为 <typeparamref name="TResult"/> 。
/// </summary>
/// <returns>异步解释结果。</returns>
Task<IResponse<TResult>> ResolveAsync();
/// <summary>
/// 解释响应消息,反序列化为 <typeparamref name="TResult"/> 后通过 <paramref name="transformer"/> 转换为 <typeparamref name="TNewResult"/> 。
/// </summary>
/// <param name="transformer">结果转换器。</param>
/// <typeparam name="TNewResult">转换后结果对象类型。</typeparam>
/// <returns>异步解释结果。</returns>
Task<IResponse<TNewResult>> ResolveAsync<TNewResult>(Func<TResult, TNewResult> transformer)
where TNewResult : class;
}
}

View File

@@ -0,0 +1,46 @@
//
// SerializeType.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Infrastructure.Protocol
{
/// <summary>
/// 序列化类型。
/// </summary>
public enum SerializeType
{
/// <summary>
/// Json默认
/// </summary>
/// <seealso ref="http://www.json.org/"/>
Json,
/// <summary>
/// Google Protocol Buffers
/// </summary>
/// <seealso ref="http://developers.google.com/protocol-buffers/"/>
Protobuf,
}
}

View File

@@ -0,0 +1,39 @@
//
// SignatureType.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Aliyun.Api.LogService.Infrastructure.Protocol
{
/// <summary>
/// 签名类型。
/// </summary>
public enum SignatureType
{
/// <summary>
/// HMAC-SHA1签名。
/// </summary>
HmacSha1,
}
}

View File

@@ -0,0 +1,921 @@
//
// Log.Generated.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// *****************************************************************************
// * NOTE: *
// * The following code has been modified by the compatibility of empty string *
// * handling between proto2 and proto3. *
// * *
// * !!! DO NOT FORGET TO MODIFY CODES AFTER REGENERATION !!! *
// * *
// * Diff: *
// * $ git diff 983301d 5d4f432 -- Log.Generated.cs *
// * *
// * For more detail: *
// * https://github.com/aliyun/aliyun-log-dotnetcore-sdk/issues/4 *
// *****************************************************************************
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: Log.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf {
/// <summary>Holder for reflection information generated from Log.proto</summary>
public static partial class LogReflection {
#region Descriptor
/// <summary>File descriptor for Log.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static LogReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CglMb2cucHJvdG8SNGFsaXl1bi5hcGkubG9nLmluZnJhc3RydWN0dXJlLnNl",
"cmlhbGl6YXRpb24ucHJvdG9idWYijwEKA0xvZxIMCgRUaW1lGAEgASgNElMK",
"CENvbnRlbnRzGAIgAygLMkEuYWxpeXVuLmFwaS5sb2cuaW5mcmFzdHJ1Y3R1",
"cmUuc2VyaWFsaXphdGlvbi5wcm90b2J1Zi5Mb2cuQ29udGVudBolCgdDb250",
"ZW50EgsKA0tleRgBIAEoCRINCgVWYWx1ZRgCIAEoCSIkCgZMb2dUYWcSCwoD",
"S2V5GAEgASgJEg0KBVZhbHVlGAIgASgJItMBCghMb2dHcm91cBJHCgRMb2dz",
"GAEgAygLMjkuYWxpeXVuLmFwaS5sb2cuaW5mcmFzdHJ1Y3R1cmUuc2VyaWFs",
"aXphdGlvbi5wcm90b2J1Zi5Mb2cSEAoIUmVzZXJ2ZWQYAiABKAkSDQoFVG9w",
"aWMYAyABKAkSDgoGU291cmNlGAQgASgJEk0KB0xvZ1RhZ3MYBiADKAsyPC5h",
"bGl5dW4uYXBpLmxvZy5pbmZyYXN0cnVjdHVyZS5zZXJpYWxpemF0aW9uLnBy",
"b3RvYnVmLkxvZ1RhZyJkCgxMb2dHcm91cExpc3QSVAoMbG9nR3JvdXBMaXN0",
"GAEgAygLMj4uYWxpeXVuLmFwaS5sb2cuaW5mcmFzdHJ1Y3R1cmUuc2VyaWFs",
"aXphdGlvbi5wcm90b2J1Zi5Mb2dHcm91cEI+qgI7QWxpeXVuLkFwaS5Mb2dT",
"ZXJ2aWNlLkluZnJhc3RydWN0dXJlLlNlcmlhbGl6YXRpb24uUHJvdG9idWZi",
"BnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log), global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Parser, new[]{ "Time", "Contents" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Types.Content), global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Types.Content.Parser, new[]{ "Key", "Value" }, null, null, null)}),
new pbr::GeneratedClrTypeInfo(typeof(global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogTag), global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogTag.Parser, new[]{ "Key", "Value" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroup), global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroup.Parser, new[]{ "Logs", "Reserved", "Topic", "Source", "LogTags" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroupList), global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroupList.Parser, new[]{ "LogGroupList_" }, null, null, null)
}));
}
#endregion
}
#region Messages
public sealed partial class Log : pb::IMessage<Log> {
private static readonly pb::MessageParser<Log> _parser = new pb::MessageParser<Log>(() => new Log());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Log> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Log() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Log(Log other) : this() {
time_ = other.time_;
contents_ = other.contents_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Log Clone() {
return new Log(this);
}
/// <summary>Field number for the "Time" field.</summary>
public const int TimeFieldNumber = 1;
private uint time_;
/// <summary>
/// UNIX Time Format
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public uint Time {
get { return time_; }
set {
time_ = value;
}
}
/// <summary>Field number for the "Contents" field.</summary>
public const int ContentsFieldNumber = 2;
private static readonly pb::FieldCodec<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Types.Content> _repeated_contents_codec
= pb::FieldCodec.ForMessage(18, global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Types.Content.Parser);
private readonly pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Types.Content> contents_ = new pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Types.Content>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Types.Content> Contents {
get { return contents_; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as Log);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(Log other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Time != other.Time) return false;
if(!contents_.Equals(other.contents_)) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Time != 0) hash ^= Time.GetHashCode();
hash ^= contents_.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (Time != 0) {
output.WriteRawTag(8);
output.WriteUInt32(Time);
}
contents_.WriteTo(output, _repeated_contents_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (Time != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Time);
}
size += contents_.CalculateSize(_repeated_contents_codec);
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(Log other) {
if (other == null) {
return;
}
if (other.Time != 0) {
Time = other.Time;
}
contents_.Add(other.contents_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Time = input.ReadUInt32();
break;
}
case 18: {
contents_.AddEntriesFrom(input, _repeated_contents_codec);
break;
}
}
}
}
#region Nested types
/// <summary>Container for nested types declared in the Log message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static partial class Types {
public sealed partial class Content : pb::IMessage<Content> {
private static readonly pb::MessageParser<Content> _parser = new pb::MessageParser<Content>(() => new Content());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Content> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Descriptor.NestedTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Content() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Content(Content other) : this() {
key_ = other.key_;
value_ = other.value_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Content Clone() {
return new Content(this);
}
/// <summary>Field number for the "Key" field.</summary>
public const int KeyFieldNumber = 1;
private string key_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Key {
get { return key_; }
set {
key_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "Value" field.</summary>
public const int ValueFieldNumber = 2;
private string value_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Value {
get { return value_; }
set {
value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as Content);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(Content other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Key != other.Key) return false;
if (Value != other.Value) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Key.Length != 0) hash ^= Key.GetHashCode();
if (Value.Length != 0) hash ^= Value.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (Key.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Key);
}
if (value_ != null) {
output.WriteRawTag(18);
output.WriteString(Value);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (Key.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Key);
}
if (value_ != null) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Value);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(Content other) {
if (other == null) {
return;
}
if (other.Key.Length != 0) {
Key = other.Key;
}
if (other.value_ != null) {
Value = other.Value;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Key = input.ReadString();
break;
}
case 18: {
Value = input.ReadString();
break;
}
}
}
}
}
}
#endregion
}
public sealed partial class LogTag : pb::IMessage<LogTag> {
private static readonly pb::MessageParser<LogTag> _parser = new pb::MessageParser<LogTag>(() => new LogTag());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<LogTag> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogReflection.Descriptor.MessageTypes[1]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogTag() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogTag(LogTag other) : this() {
key_ = other.key_;
value_ = other.value_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogTag Clone() {
return new LogTag(this);
}
/// <summary>Field number for the "Key" field.</summary>
public const int KeyFieldNumber = 1;
private string key_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Key {
get { return key_; }
set {
key_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "Value" field.</summary>
public const int ValueFieldNumber = 2;
private string value_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Value {
get { return value_; }
set {
value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as LogTag);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(LogTag other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Key != other.Key) return false;
if (Value != other.Value) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Key.Length != 0) hash ^= Key.GetHashCode();
if (Value.Length != 0) hash ^= Value.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (Key.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Key);
}
if (value_ != null) {
output.WriteRawTag(18);
output.WriteString(Value);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (Key.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Key);
}
if (value_ != null) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Value);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(LogTag other) {
if (other == null) {
return;
}
if (other.Key.Length != 0) {
Key = other.Key;
}
if (other.value_ != null) {
Value = other.Value;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Key = input.ReadString();
break;
}
case 18: {
Value = input.ReadString();
break;
}
}
}
}
}
public sealed partial class LogGroup : pb::IMessage<LogGroup> {
private static readonly pb::MessageParser<LogGroup> _parser = new pb::MessageParser<LogGroup>(() => new LogGroup());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<LogGroup> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogReflection.Descriptor.MessageTypes[2]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogGroup() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogGroup(LogGroup other) : this() {
logs_ = other.logs_.Clone();
reserved_ = other.reserved_;
topic_ = other.topic_;
source_ = other.source_;
logTags_ = other.logTags_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogGroup Clone() {
return new LogGroup(this);
}
/// <summary>Field number for the "Logs" field.</summary>
public const int LogsFieldNumber = 1;
private static readonly pb::FieldCodec<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log> _repeated_logs_codec
= pb::FieldCodec.ForMessage(10, global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log.Parser);
private readonly pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log> logs_ = new pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.Log> Logs {
get { return logs_; }
}
/// <summary>Field number for the "Reserved" field.</summary>
public const int ReservedFieldNumber = 2;
private string reserved_ = "";
/// <summary>
/// reserved fields
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Reserved {
get { return reserved_; }
set {
reserved_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "Topic" field.</summary>
public const int TopicFieldNumber = 3;
private string topic_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Topic {
get { return topic_; }
set {
topic_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "Source" field.</summary>
public const int SourceFieldNumber = 4;
private string source_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Source {
get { return source_; }
set {
source_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "LogTags" field.</summary>
public const int LogTagsFieldNumber = 6;
private static readonly pb::FieldCodec<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogTag> _repeated_logTags_codec
= pb::FieldCodec.ForMessage(50, global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogTag.Parser);
private readonly pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogTag> logTags_ = new pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogTag>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogTag> LogTags {
get { return logTags_; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as LogGroup);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(LogGroup other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if(!logs_.Equals(other.logs_)) return false;
if (Reserved != other.Reserved) return false;
if (Topic != other.Topic) return false;
if (Source != other.Source) return false;
if(!logTags_.Equals(other.logTags_)) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
hash ^= logs_.GetHashCode();
if (Reserved.Length != 0) hash ^= Reserved.GetHashCode();
if (Topic.Length != 0) hash ^= Topic.GetHashCode();
if (Source.Length != 0) hash ^= Source.GetHashCode();
hash ^= logTags_.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
logs_.WriteTo(output, _repeated_logs_codec);
if (Reserved.Length != 0) {
output.WriteRawTag(18);
output.WriteString(Reserved);
}
if (Topic.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Topic);
}
if (Source.Length != 0) {
output.WriteRawTag(34);
output.WriteString(Source);
}
logTags_.WriteTo(output, _repeated_logTags_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
size += logs_.CalculateSize(_repeated_logs_codec);
if (Reserved.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Reserved);
}
if (Topic.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Topic);
}
if (Source.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Source);
}
size += logTags_.CalculateSize(_repeated_logTags_codec);
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(LogGroup other) {
if (other == null) {
return;
}
logs_.Add(other.logs_);
if (other.Reserved.Length != 0) {
Reserved = other.Reserved;
}
if (other.Topic.Length != 0) {
Topic = other.Topic;
}
if (other.Source.Length != 0) {
Source = other.Source;
}
logTags_.Add(other.logTags_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
logs_.AddEntriesFrom(input, _repeated_logs_codec);
break;
}
case 18: {
Reserved = input.ReadString();
break;
}
case 26: {
Topic = input.ReadString();
break;
}
case 34: {
Source = input.ReadString();
break;
}
case 50: {
logTags_.AddEntriesFrom(input, _repeated_logTags_codec);
break;
}
}
}
}
}
public sealed partial class LogGroupList : pb::IMessage<LogGroupList> {
private static readonly pb::MessageParser<LogGroupList> _parser = new pb::MessageParser<LogGroupList>(() => new LogGroupList());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<LogGroupList> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogReflection.Descriptor.MessageTypes[3]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogGroupList() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogGroupList(LogGroupList other) : this() {
logGroupList_ = other.logGroupList_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public LogGroupList Clone() {
return new LogGroupList(this);
}
/// <summary>Field number for the "logGroupList" field.</summary>
public const int LogGroupList_FieldNumber = 1;
private static readonly pb::FieldCodec<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroup> _repeated_logGroupList_codec
= pb::FieldCodec.ForMessage(10, global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroup.Parser);
private readonly pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroup> logGroupList_ = new pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroup>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf.LogGroup> LogGroupList_ {
get { return logGroupList_; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as LogGroupList);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(LogGroupList other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if(!logGroupList_.Equals(other.logGroupList_)) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
hash ^= logGroupList_.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
logGroupList_.WriteTo(output, _repeated_logGroupList_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
size += logGroupList_.CalculateSize(_repeated_logGroupList_codec);
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(LogGroupList other) {
if (other == null) {
return;
}
logGroupList_.Add(other.logGroupList_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
logGroupList_.AddEntriesFrom(input, _repeated_logGroupList_codec);
break;
}
}
}
}
}
#endregion
}
#endregion Designer generated code

View File

@@ -0,0 +1,39 @@
/******************************************************************************
* Compile command:
* $ protoc --csharp_out=. --csharp_opt=file_extension=.Generated.cs Log.proto
******************************************************************************/
syntax = "proto3";
option csharp_namespace = "Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf";
package aliyun.api.log.infrastructure.serialization.protobuf;
message Log
{
uint32 Time = 1;// UNIX Time Format
message Content
{
string Key = 1;
string Value = 2;
}
repeated Content Contents= 2;
}
message LogTag
{
string Key = 1;
string Value = 2;
}
message LogGroup
{
repeated Log Logs= 1;
string Reserved = 2; // reserved fields
string Topic = 3;
string Source = 4;
repeated LogTag LogTags = 6;
}
message LogGroupList
{
repeated LogGroup logGroupList = 1;
}

View File

@@ -0,0 +1,109 @@
//
// LogExtensions.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using Aliyun.Api.LogService.Domain.Log;
namespace Aliyun.Api.LogService.Infrastructure.Serialization.Protobuf
{
public static class LogExtensions
{
public static LogInfo ToDomainModel(this Log proto)
=> proto == null
? null
: new LogInfo
{
Time = DateTimeOffset.FromUnixTimeSeconds(proto.Time),
Contents = proto.Contents?
.ToDictionary(x => x.Key, x => x.Value) // NOTE: potential `ArgumentException` when key duplicated.
};
public static LogGroupInfo ToDomainModel(this LogGroup proto)
=> proto == null
? null
: new LogGroupInfo
{
Topic = proto.Topic,
Source = proto.Source,
LogTags = proto.LogTags?
.ToDictionary(x => x.Key, x => x.Value), // NOTE: potential `ArgumentException` when key duplicated.
Logs = proto.Logs?
.Select(x => x.ToDomainModel())
.ToList()
};
public static IList<LogGroupInfo> ToDomainModel(this LogGroupList proto)
=> proto?.LogGroupList_?
.Select(x => x.ToDomainModel())
.ToList();
public static Log ToProtoModel(this LogInfo domain)
=> domain == null
? null
: new Log
{
Time = (UInt32) domain.Time.ToUnixTimeSeconds(),
Contents =
{
domain.Contents?
.Select(kv => new Log.Types.Content
{
Key = kv.Key,
Value = kv.Value ?? String.Empty // Empty is allowed, but not null.
})
}
};
public static LogGroup ToProtoModel(this LogGroupInfo domain)
=> domain == null
? null
: new LogGroup
{
// https://github.com/aliyun/aliyun-log-dotnetcore-sdk/issues/14
Topic = domain.Topic ?? String.Empty, // Empty is allowed, but not null.
Source = domain.Source ?? String.Empty, // Empty is allowed, but not null.
LogTags =
{
domain.LogTags?
.Select(x => new LogTag
{
Key = x.Key,
Value = x.Value ?? String.Empty // Empty is allowed, but not null.
})
?? Enumerable.Empty<LogTag>()
},
Logs =
{
domain.Logs?
.Select(x => x.ToProtoModel())
?? Enumerable.Empty<Log>()
}
};
}
}

View File

@@ -0,0 +1,42 @@
//
// LogServiceClientBuilders.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using Aliyun.Api.LogService.Infrastructure.Protocol.Http;
namespace Aliyun.Api.LogService
{
/// <summary>
/// <see cref="ILogServiceClient"/> 实现类构建器。
/// </summary>
public static class LogServiceClientBuilders
{
/// <summary>
/// 实现 HTTP 协议的构建器。
/// </summary>
public static HttpLogServiceClientBuilder HttpBuilder
=> new HttpLogServiceClientBuilder();
}
}

View File

@@ -0,0 +1,951 @@
//
// LogServiceClientExtensions.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Aliyun.Api.LogService.Domain.Config;
using Aliyun.Api.LogService.Domain.Log;
using Aliyun.Api.LogService.Domain.LogStore;
using Aliyun.Api.LogService.Domain.LogStore.Index;
using Aliyun.Api.LogService.Domain.LogStore.Shard;
using Aliyun.Api.LogService.Domain.LogStore.Shipper;
using Aliyun.Api.LogService.Domain.MachineGroup;
using Aliyun.Api.LogService.Domain.Project;
using Aliyun.Api.LogService.Infrastructure.Protocol;
using Aliyun.Api.LogService.Utils;
namespace Aliyun.Api.LogService
{
public static class LogServiceClientExtensions
{
#region LogStore
/// <summary>
/// 在 Project 下创建 Logstore。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="ttl">数据的保存时间单位为天范围1~365额外需求请提交工单。</param>
/// <param name="shardCount">该 Logstore 的 Shard 数量,单位为个,范围为 1~10。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateLogStoreAsync"/>
public static Task<IResponse> CreateLogStoreAsync(this ILogServiceClient client,
String logstoreName, Int32 ttl, Int32 shardCount,
String project = null)
=> client.CreateLogStoreAsync(new CreateLogStoreRequest(logstoreName, ttl, shardCount)
{
ProjectName = project
});
/// <summary>
/// 删除 Logstore包括所有 Shard 数据,以及索引等。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.DeleteLogStoreAsync"/>
public static Task<IResponse> DeleteLogStoreAsync(this ILogServiceClient client,
String logstoreName,
String project = null)
=> client.DeleteLogStoreAsync(new DeleteLogStoreRequest(logstoreName)
{
ProjectName = project
});
/// <summary>
/// 更新 Logstore 的属性。目前只支持更新 TTL和shard 属性。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="ttl">数据的保存时间单位为天范围1~365额外需求请提交工单。</param>
/// <param name="shardCount">该 Logstore 的 Shard 数量,单位为个,范围为 1~10。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.UpdateLogStoreAsync"/>
public static Task<IResponse> UpdateLogStoreAsync(this ILogServiceClient client,
String logstoreName, Int32 ttl, Int32 shardCount,
String project = null)
=> client.UpdateLogStoreAsync(new UpdateLogStoreRequest(logstoreName, ttl, shardCount)
{
ProjectName = project
});
/// <summary>
/// 查看 Logstore 属性。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.UpdateLogStoreAsync"/>
public static Task<IResponse<GetLogStoreResult>> GetLogStoreAsync(this ILogServiceClient client,
String logstoreName,
String project = null)
=> client.GetLogStoreAsync(new GetLogStoreRequest(logstoreName)
{
ProjectName = project
});
/// <summary>
/// 接口列出指定 Project 下的所有 Logstore 的名称。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">用于请求的 Logstore 名称(支持部分匹配)。</param>
/// <param name="offset">返回记录的起始位置,默认值为 1。</param>
/// <param name="size">每页返回最大条目,默认 500最大值。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.ListLogStoreAsync"/>
public static Task<IResponse<ListLogStoreResult>> ListLogStoreAsync(this ILogServiceClient client,
String logstoreName = null, Int32 offset = ListLogStoreRequest.DefaultOffset, Int32 size = ListLogStoreRequest.DefaultSize, String project = null)
=> client.ListLogStoreAsync(new ListLogStoreRequest
{
LogstoreName = logstoreName,
Offset = offset,
Size = size,
ProjectName = project
});
#region Shard
/// <summary>
/// 列出 Logstore 下当前所有可用 Shard。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.ListShardsAsync"/>
public static Task<IResponse<IList<ShardInfo>>> ListShardsAsync(this ILogServiceClient client,
String logstoreName,
String project = null)
=> client.ListShardsAsync(new ListShardRequest(logstoreName)
{
ProjectName = project
});
/// <summary>
/// 分裂一个指定的 readwrite 状态的 Shard。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称</param>
/// <param name="shardId">Shard ID</param>
/// <param name="splitKey">split 切分位置</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.SplitShardAsync"/>
public static Task<IResponse<IList<ShardInfo>>> SplitShardAsync(this ILogServiceClient client,
String logstoreName, Int32 shardId, String splitKey,
String project = null)
=> client.SplitShardAsync(new SplitShardRequest(logstoreName, shardId, splitKey)
{
ProjectName = project
});
/// <summary>
/// 合并两个相邻的 readwrite 状态的 Shards。在参数中指定一个 shardid服务端自动找相邻的下一个 Shard。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称</param>
/// <param name="shardId">Shard ID</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.MergeShardsAsync"/>
public static Task<IResponse<IList<ShardInfo>>> MergeShardsAsync(this ILogServiceClient client,
String logstoreName, Int32 shardId,
String project = null)
=> client.MergeShardsAsync(new MergeShardRequest(logstoreName, shardId)
{
ProjectName = project
});
/// <summary>
/// 根据时间获得游标cursor
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称</param>
/// <param name="shardId">Shard ID</param>
/// <param name="from">时间点UNIX下秒数或 beginend</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetCursorAsync"/>
public static Task<IResponse<GetCursorResult>> GetCursorAsync(this ILogServiceClient client,
String logstoreName, Int32 shardId, String from,
String project = null)
=> client.GetCursorAsync(new GetCursorRequest(logstoreName, shardId, from)
{
ProjectName = project
});
#endregion Shard
#region Shipper
/// <summary>
/// 查询日志投递任务状态。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称,同一 Project 下唯一。</param>
/// <param name="shipperName">日志投递规则名称,同一 Logstore 下唯一。</param>
/// <param name="from">日志投递任务创建时间区间。</param>
/// <param name="to">日志投递任务创建时间区间。</param>
/// <param name="status">默认为空,表示返回所有状态的任务,目前支持 success/fail/running 等状态。</param>
/// <param name="offset">返回指定时间区间内投递任务的起始数目,默认值为 0。</param>
/// <param name="size">返回指定时间区间内投递任务的数目,默认值为 100最大为 500。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetShipperStatusAsync"/>
public static Task<IResponse<GetShipperResult>> GetShipperStatusAsync(this ILogServiceClient client,
String logstoreName, String shipperName, DateTimeOffset from, DateTimeOffset to,
String status = null, Int32 offset = GetShipperRequest.DefaultOffset, Int32 size = GetShipperRequest.DefaultSize, String project = null)
=> client.GetShipperStatusAsync(new GetShipperRequest(logstoreName, shipperName, (Int32)from.ToUnixTimeSeconds(), (Int32) to.ToUnixTimeSeconds())
{
Status = status,
Offset = offset,
Size = size,
ProjectName = project
});
/// <summary>
/// 重新执行失败的日志投递任务。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称,同一 Project 下唯一。</param>
/// <param name="shipperName">日志投递规则名称,同一 Logstore 下唯一。</param>
/// <param name="taskIds">需要重试的任务ID。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.RetryShipperTaskAsync"/>
public static Task<IResponse> RetryShipperTaskAsync(this ILogServiceClient client,
String logstoreName, String shipperName, IEnumerable<String> taskIds,
String project = null)
=> client.RetryShipperTaskAsync(new RetryShipperRequest(logstoreName, shipperName, taskIds)
{
ProjectName = project
});
/// <summary>
/// 重新执行失败的日志投递任务。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称,同一 Project 下唯一。</param>
/// <param name="shipperName">日志投递规则名称,同一 Logstore 下唯一。</param>
/// <param name="taskIds">需要重试的任务ID。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.RetryShipperTaskAsync"/>
/// <remarks>
/// 由于此方法存在变长参数,不支持使用可选参数覆盖 project需要覆盖 project参数请使用
/// <see cref="RetryShipperTaskAsync(Aliyun.Api.LogService.ILogServiceClient,string,string,System.Collections.Generic.IEnumerable{string},string)"/> 版本。
/// </remarks>
public static Task<IResponse> RetryShipperTaskAsync(this ILogServiceClient client,
String logstoreName, String shipperName, params String[] taskIds)
=> client.RetryShipperTaskAsync(new RetryShipperRequest(logstoreName, shipperName, taskIds));
#endregion Shipper
#region Index
/// <summary>
/// 开启日志库索引。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="line">全文索引对于日志中value的索引属性全文索引和字段查询必须至少配置一类。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateIndexAsync"/>
/// <exception cref="ArgumentException"><paramref /> 为空</exception>
public static Task<IResponse> CreateIndexAsync(this ILogServiceClient client,
String logstoreName, IndexLineInfo line,
String project = null)
{
Ensure.NotNull(line, nameof(line));
return client.CreateIndexAsync(new CreateIndexRequest(logstoreName, line)
{
ProjectName = project
});
}
/// <summary>
/// 开启日志库索引。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="keys">字段查询对于具体字段的value索引属性全文索引和字段查询必须至少配置一类。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateIndexAsync"/>
/// <exception cref="ArgumentException"><paramref name="keys"/> 为空</exception>
public static Task<IResponse> CreateIndexAsync(this ILogServiceClient client,
String logstoreName, IDictionary<String, IndexKeyInfo> keys,
String project = null)
{
Ensure.NotEmpty(keys, nameof(keys));
return client.CreateIndexAsync(new CreateIndexRequest(logstoreName, keys)
{
ProjectName = project
});
}
/// <summary>
/// 开启日志库索引。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="line">全文索引对于日志中value的索引属性全文索引和字段查询必须至少配置一类。</param>
/// <param name="keys">字段查询对于具体字段的value索引属性全文索引和字段查询必须至少配置一类。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateIndexAsync"/>
/// <exception cref="ArgumentException"><paramref /> 和 <paramref name="keys"/> 同时为空</exception>
public static Task<IResponse> CreateIndexAsync(this ILogServiceClient client,
String logstoreName, IndexLineInfo line, IDictionary<String, IndexKeyInfo> keys,
String project = null)
{
if (line == null && keys.IsEmpty())
{
throw new ArgumentException("line and keys cannot be both empty.");
}
return client.CreateIndexAsync(new CreateIndexRequest(logstoreName, line, keys)
{
ProjectName = project
});
}
/// <summary>
/// 开启日志库索引。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="keysBuilder">字段查询构建器。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateIndexAsync"/>
/// <exception cref="ArgumentException"><paramref name="keysBuilder"/> 为空或没有任何keys被构建</exception>
public static Task<IResponse> CreateIndexAsync(this ILogServiceClient client,
String logstoreName, Action<IndexKeysBuilder> keysBuilder,
String project = null)
{
IDictionary<String, IndexKeyInfo> keys;
if (keysBuilder != null)
{
var builder = new IndexKeysBuilder();
keysBuilder(builder);
keys = builder.Build();
} else
{
keys = null;
}
return client.CreateIndexAsync(logstoreName, keys, project);
}
/// <summary>
/// 开启日志库索引。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">Logstore 的名称,在 Project 下必须唯一。</param>
/// <param name="line">全文索引对于日志中value的索引属性全文索引和字段查询必须至少配置一类。</param>
/// <param name="keysBuilder">字段查询构建器。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateIndexAsync"/>
/// <exception cref="ArgumentException"><paramref/> 和 <paramref name="keysBuilder"/> 同时为空</exception>
public static Task<IResponse> CreateIndexAsync(this ILogServiceClient client,
String logstoreName, IndexLineInfo line, Action<IndexKeysBuilder> keysBuilder,
String project = null)
{
IDictionary<String, IndexKeyInfo> keys;
if (keysBuilder != null)
{
var builder = new IndexKeysBuilder();
keysBuilder(builder);
keys = builder.Build();
} else
{
keys = null;
}
return client.CreateIndexAsync(logstoreName, line, keys, project);
}
#endregion Index
#endregion LogStore
#region Log
/// <summary>
/// 向指定的 LogStore 写入日志数据。目前仅支持写入 PB 格式的 <see cref="LogGroupInfo"/> 日志数据。写入时有两种模式:
/// <list type="bullet">
/// <item>
/// <description>负载均衡模式LoadBalance: 自动根据 Logstore 下所有可写的 shard 进行负载均衡写入。该方法对写入可用性较高SLA: 99.95%),适合写入与消费数据与 shard 无关的场景,例如不保序。</description>
/// </item>
/// <item>
/// <description>根据 Key 路由 shard 模式KeyHash写入时需要传递一个 Key服务端自动根据 Key 选择当前符合该 Key 区间的 Shard 写入。例如,可以将某个生产者(例如 instance根据名称 Hash 到固定 Shard 上,这样就能保证写入与消费在该 Shard 上是严格有序的(在 Merge/Split 过程中能够严格保证对于 Key 在一个时间点只会出现在一个 Shard 上,参见 <see ref="http://help.aliyun.com/document_detail/28976.html">shard 数据模型</see>)。</description>
/// </item>
/// </list>
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称。</param>
/// <param name="logGroup">一组日志。</param>
/// <param name="hashKey">(可选)标记日志应该路由到哪个 shard 的标记。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.PostLogStoreLogsAsync"/>
public static Task<IResponse> PostLogStoreLogsAsync(this ILogServiceClient client,
String logstoreName, LogGroupInfo logGroup,
String hashKey = null, String project = null)
=> client.PostLogStoreLogsAsync(new PostLogsRequest(logstoreName, logGroup)
{
HashKey = hashKey,
ProjectName = project
});
/// <summary>
/// 根据游标、数量获得日志。获得日志时必须指定 shard。
/// 如果在 storm 等情况下可以通过 LoghubClientLib 进行选举与协同消费。
/// 目前仅支持读取 PB 格式 LogGroupList 数据。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstoreName">日志库名称</param>
/// <param name="shardId">Shard ID</param>
/// <param name="cursor">游标,用以表示从什么位置开始读取数据,相当于起点。</param>
/// <param name="count">返回的 loggroup 数目,范围为 0~1000。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.PullLogsAsync"/>
public static Task<IResponse<PullLogsResult>> PullLogsAsync(this ILogServiceClient client,
String logstoreName, Int32 shardId, String cursor, Int32 count,
String project = null)
=> client.PullLogsAsync(new PullLogsRequest(logstoreName, shardId, cursor, count)
{
ProjectName = project
});
/// <summary>
/// GetLogs 接口查询指定 Project 下某个 Logstore 中的日志数据。还可以通过指定相关参数仅查询符合指定条件的日志数据。
/// 当日志写入到 Logstore 中日志服务的查询接口GetHistograms 和 GetLogs能够查到该日志的延时因写入日志类型不同而异。日志服务按日志时间戳把日志分为如下两类
/// <list type="bullet">
/// <item><description>实时数据:日志中时间点为服务器当前时间点 (-180秒900秒]。例如,日志时间为 UTC 2014-09-25 12:03:00服务器收到时为 UTC 2014-09-25 12:05:00则该日志被作为实时数据处理一般出现在正常场景下。</description></item>
/// <item><description>历史数据:日志中时间点为服务器当前时间点 [-7 x 86400秒, -180秒)。例如,日志时间为 UTC 2014-09-25 12:00:00服务器收到时为 UTC 2014-09-25 12:05:00则该日志被作为历史数据处理一般出现在补数据场景下。</description></item>
/// </list>
///
/// 其中实时数据写入至可查询的最大延时为3秒99.9%情况下1秒内即可查询
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstorename">需要查询日志的 Logstore 名称。</param>
/// <param name="from">查询开始时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。</param>
/// <param name="to">查询结束时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。</param>
/// <param name="topic">查询日志主题。</param>
/// <param name="query">查询表达式。关于查询表达式的详细语法,请参考 查询语法。</param>
/// <param name="line">请求返回的最大日志条数。取值范围为 0~100默认值为 100。</param>
/// <param name="offset">请求返回日志的起始点。取值范围为 0 或正整数,默认值为 0。</param>
/// <param name="reverse">是否按日志时间戳逆序返回日志。true 表示逆序false 表示顺序,默认值为 false。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetLogsAsync"/>
public static Task<IResponse<GetLogsResult>> GetLogsAsync(this ILogServiceClient client,
String logstorename, DateTimeOffset from, DateTimeOffset to,
String topic = null, String query = null, Int32 line = GetLogsRequest.DefaultLine, Int32 offset = GetLogsRequest.DefaultOffset, Boolean reverse = GetLogsRequest.DefaultReverse, String project = null)
=> client.GetLogsAsync(new GetLogsRequest(logstorename, (Int32)from.ToUnixTimeSeconds(), (Int32) to.ToUnixTimeSeconds())
{
Topic = topic,
Query = query,
Line = line,
Offset = offset,
Reverse = reverse,
ProjectName = project
});
/// <summary>
/// 统计Project下所有日志。
/// <list type="bullet">
/// <item><description>该接口的query是一个标准的SQL查询语句。</description></item>
/// <item><description>查询的Project在请求的域名中指定。</description></item>
/// <item><description>查询的logstore在查询语句的from条件中指定。logstore相当于SQL中的表。</description></item>
/// <item><description>在查询的SQL条件中必须指定要查询的时间范围时间范围由__date__(timestamp类型)来指定或__time__(int 类型单位是unix_time)来指定。</description></item>
/// <item><description>如上所述,该接口一次调用必须要在限定时间内返回结果,每次查询只能扫描指定条数的日志量。如果一次请求需要处理的数据量非常大的时候,该请求会返回不完整的结果(并在返回结果中的 x-log-progress 成员标示是否完整)。如此同时,服务端会缓存 15 分钟内的查询结果。当查询请求的结果有部分被缓存命中,则服务端会在这次请求中继续扫描未被缓存命中的日志数据。为了减少您合并多次查询结果的工作量,服务端会把缓存命中的查询结果与本次查询新命中的结果合并返回给您。因此,日志服务可以让您通过以相同参数反复调用该接口来获取最终完整结果。因为您的查询涉及的日志数据量变化非常大,日志服务 API 无法预测需要调用多少次该接口而获取完整结果。所以需要用户通过检查每次请求的返回结果中的x-log-progress成员状态值来确定是否需要继续。需要注意的是每次重复调用该接口都会重新消耗相同数量的查询 CU。</description></item>
/// </list>
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="query">查询sql条件。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetProjectLogsAsync"/>
public static Task<IResponse<GetLogsResult>> GetProjectLogsAsync(this ILogServiceClient client,
String query,
String project = null)
=> client.GetProjectLogsAsync(new GetProjectLogsRequest(query)
{
ProjectName = project
});
/// <summary>
/// GetHistograms 接口查询指定的 Project 下某个 Logstore 中日志的分布情况。还可以通过指定相关参数仅查询符合指定条件的日志分布情况。
/// 当日志写入到 logstore 中日志服务的查询接口GetHistograms 和 GetLogs能够查到该日志的延时因写入日志类型不同而异。日志服务按日志时间戳把日志分为如下两类
/// <list type="bullet">
/// <item><description>实时数据:日志中时间点为服务器当前时间点 (-180秒900秒]。例如,日志时间为 UTC 2014-09-25 12:03:00服务器收到时为 UTC 2014-09-25 12:05:00则该日志被作为实时数据处理一般出现在正常场景下。</description></item>
/// <item><description>历史数据:日志中时间点为服务器当前时间点 [-7 x 86400秒, -180秒)。例如,日志时间为 UTC 2014-09-25 12:00:00服务器收到时为 UTC 2014-09-25 12:05:00则该日志被作为历史数据处理一般出现在补数据场景下。</description></item>
/// </list>
///
/// 其中实时数据写入至可查询的延时为3秒。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="logstorename">需要查询日志的 Logstore 名称。</param>
/// <param name="from">查询开始时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。</param>
/// <param name="to">查询结束时间点(精度为秒,从 1970-1-1 00:00:00 UTC 计算起的秒数)。</param>
/// <param name="topic">查询日志主题。</param>
/// <param name="query">查询表达式。关于查询表达式的详细语法,请参考 查询语法。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetHistogramsAsync"/>
public static Task<IResponse<GetLogHistogramsResult>> GetHistogramsAsync(this ILogServiceClient client,
String logstorename, DateTimeOffset from, DateTimeOffset to,
String topic = null, String query = null, String project = null)
=> client.GetHistogramsAsync(new GetLogHistogramsRequest(logstorename, (Int32)from.ToUnixTimeSeconds(), (Int32) to.ToUnixTimeSeconds())
{
Topic = topic,
Query = query,
ProjectName = project
});
#endregion Log
#region MachineGroup
/// <summary>
/// 根据需求创建一组机器,用以日志收集下发配置。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">机器分组名称。</param>
/// <param name="machineIdentifyType">机器标识类型,分为 ip 和 userdefined 两种。</param>
/// <param name="machineList">具体的机器标识,可以是 IP 或 userdefined-id。</param>
/// <param name="groupType">机器分组类型,默认为空。</param>
/// <param name="groupTopic">机器分组的 topic默认为空。</param>
/// <param name="externalName">机器分组所依赖的外部管理标识,默认为空。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateMachineGroupAsync"/>
public static Task<IResponse> CreateMachineGroupAsync(this ILogServiceClient client,
String groupName, String machineIdentifyType, IEnumerable<String> machineList,
String groupType = null, String groupTopic = null, String externalName = null, String project = null)
=> client.CreateMachineGroupAsync(new CreateMachineGroupRequest(groupName, machineIdentifyType, machineList)
{
GroupType = groupType,
GroupAttribute = groupTopic == null && externalName == null
? null
: new MachineGroupAttributeInfo
{
GroupTopic = groupTopic,
ExternalName = externalName
},
ProjectName = project
});
/// <summary>
/// 删除机器组,如果机器组上有配置,则 Logtail 上对应的配置也会被删除。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">机器分组名称。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.DeleteMachineGroupAsync"/>
public static Task<IResponse> DeleteMachineGroupAsync(this ILogServiceClient client,
String groupName,
String project = null)
=> client.DeleteMachineGroupAsync(new DeleteMachineGroupRequest(groupName)
{
ProjectName = project
});
/// <summary>
/// 更新机器组信息,如果机器组已应用配置,则新加入、减少机器会自动增加、移除配置。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">机器分组名称。</param>
/// <param name="machineIdentifyType">机器标识类型,分为 ip 和 userdefined 两种。</param>
/// <param name="machineList">具体的机器标识,可以是 IP 或 userdefined-id。</param>
/// <param name="groupType">机器分组类型,默认为空。</param>
/// <param name="groupTopic">机器分组的 topic默认为空。</param>
/// <param name="externalName">机器分组所依赖的外部管理标识,默认为空。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.UpdateMachineGroupAsync"/>
public static Task<IResponse> UpdateMachineGroupAsync(this ILogServiceClient client,
String groupName, String machineIdentifyType, IEnumerable<String> machineList,
String groupType = null, String groupTopic = null, String externalName = null, String project = null)
=> client.UpdateMachineGroupAsync(new UpdateMachineGroupRequest(groupName, machineIdentifyType, machineList)
{
GroupType = groupType,
GroupAttribute = groupTopic == null && externalName == null
? null
: new MachineGroupAttributeInfo
{
GroupTopic = groupTopic,
ExternalName = externalName
},
ProjectName = project
});
/// <summary>
/// 列出 MachineGroup 信息。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">返回记录的起始位置,默认为 0。</param>
/// <param name="offset">每页返回最大条目,默认 500最大值。</param>
/// <param name="size">用于过滤的机器组名称(支持部分匹配)。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.ListMachineGroupAsync"/>
public static Task<IResponse<ListMachineGroupResult>> ListMachineGroupAsync(this ILogServiceClient client,
String groupName = null, Int32 offset = ListMachineGroupRequest.DefaultOffset, Int32 size = ListMachineGroupRequest.DefaultSize, String project = null)
=> client.ListMachineGroupAsync(new ListMachineGroupRequest
{
GroupName = groupName,
Offset = offset,
Size = size,
ProjectName = project
});
/// <summary>
/// 查看具体的 MachineGroup 信息。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">机器分组名称。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetMachineGroupAsync"/>
public static Task<IResponse<GetMachineGroupResult>> GetMachineGroupAsync(this ILogServiceClient client,
String groupName,
String project = null)
=> client.GetMachineGroupAsync(new GetMachineGroupRequest(groupName)
{
ProjectName = project
});
/// <summary>
/// 将配置应用到机器组。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">机器分组名称。</param>
/// <param name="configName">日志配置名称。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.ApplyConfigToMachineGroupAsync"/>
public static Task<IResponse> ApplyConfigToMachineGroupAsync(this ILogServiceClient client,
String groupName, String configName,
String project = null)
=> client.ApplyConfigToMachineGroupAsync(new ApplyConfigToMachineGroupRequest(groupName, configName)
{
ProjectName = project
});
/// <summary>
/// 从机器组中删除配置。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">机器分组名称。</param>
/// <param name="configName">日志配置名称。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.RemoveConfigFromMachineGroupAsync"/>
public static Task<IResponse> RemoveConfigFromMachineGroupAsync(this ILogServiceClient client,
String groupName, String configName,
String project = null)
=> client.RemoveConfigFromMachineGroupAsync(new RemoveConfigFromMachineGroupRequest(groupName, configName)
{
ProjectName = project
});
/// <summary>
/// 获得 MachineGroup 下属于用户并与 Server 端连接的机器状态信息。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">用于过滤的机器组名称(支持部分匹配)。</param>
/// <param name="offset">返回记录的起始位置,默认为 0。</param>
/// <param name="size">每页返回最大条目,默认 500最大值。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.ListMachinesAsync"/>
public static Task<IResponse<ListMachinesResult>> ListMachinesAsync(this ILogServiceClient client,
String groupName,
Int32 offset = ListMachinesRequest.DefaultOffset, Int32 size = ListMachinesRequest.DefaultSize, String project = null)
=> client.ListMachinesAsync(new ListMachinesRequest(groupName)
{
Offset = offset,
Size = size,
ProjectName = project
});
/// <summary>
/// 获得 MachineGroup 上已经被应用的配置名称。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="groupName">机器分组名称。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetAppliedConfigsAsync"/>
public static Task<IResponse<GetAppliedConfigsResult>> GetAppliedConfigsAsync(this ILogServiceClient client,
String groupName,
String project = null)
=> client.GetAppliedConfigsAsync(new GetAppliedConfigsRequest(groupName)
{
ProjectName = project
});
#endregion MachineGroup
#region Config
/// <summary>
/// 在 Project 下创建日志配置。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="configName">日志配置名称, Project 下唯一。</param>
/// <param name="inputType">输入类型,现在只支持 file。</param>
/// <param name="inputDetail">输入详情。</param>
/// <param name="outputType">输出类型,现在只支持 LogService。</param>
/// <param name="outputDetail">输出详情。</param>
/// <param name="logSample">Logtail 配置日志样例,最大支持 1000 字节。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateConfigAsync"/>
public static Task<IResponse> CreateConfigAsync(this ILogServiceClient client,
String configName, String inputType, ConfigInputDetailInfo inputDetail, String outputType, ConfigOutputDetailInfo outputDetail,
String logSample = null, String project = null)
=> client.CreateConfigAsync(new CreateConfigRequest(configName, inputType, inputDetail, outputType, outputDetail)
{
LogSample = logSample,
ProjectName = project
});
/// <summary>
/// 在 Project 下创建日志配置。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="configName">日志配置名称, Project 下唯一。</param>
/// <param name="logstoreName"></param>
/// <param name="logType">日志类型,现在只支持 common_reg_log。</param>
/// <param name="logPath">日志所在的父目录,例如 /var/logs/。</param>
/// <param name="filePattern">日志文件的Pattern例如 access*.log。</param>
/// <param name="localStorage">是否打开本地缓存,在服务端之间链路断开的情况下,本地可以缓存 1GB 日志。</param>
/// <param name="timeFormat">日志时间格式, 如 %Y/%m/%d %H:%M:%S。</param>
/// <param name="logBeginRegex">日志首行特征(正则表达式),由于匹配多行日志组成一条 log 的情况。</param>
/// <param name="regex">日志对提取正则表达式。</param>
/// <param name="key">日志提取后所生成的 Key。</param>
/// <param name="filterKey">用于过滤日志所用到的 key只有 key 的值满足对应 filterRegex 列中设定的正则表达式日志才是符合要求的。</param>
/// <param name="filterRegex">和每个 filterKey 对应的正则表达式, filterRegex 的长度和 filterKey 的长度必须相同。</param>
/// <param name="topicFormat">Topic 生成方式,支持以下四种类型:
/// <list type="bullet">
/// <item><description>用于将日志文件路径的某部分作为 topic如 /var/log/(.*).log。</description></item>
/// <item><description>none表示 topic 为空。</description></item>
/// <item><description>default表示将日志文件路径作为 topic。</description></item>
/// <item><description>group_topic表示将应用该配置的机器组 topic 属性作为 topic。</description></item>
/// </list>
/// </param>
/// <param name="preserve">true 代表监控目录永不超时false 代表监控目录 30 分钟超时,默认值为 true。</param>
/// <param name="preserveDepth">当设置 preserve 为 false 时,指定监控不超时目录的深度,最大深度支持 3。</param>
/// <param name="fileEncoding">支持两种类型utf8、gbk。</param>
/// <param name="logSample">Logtail 配置日志样例,最大支持 1000 字节。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateConfigAsync"/>
public static Task<IResponse> CreateFileToLogServiceConfigAsync(this ILogServiceClient client,
String configName, String logstoreName, String logType, String logPath, String filePattern, Boolean localStorage, String timeFormat, String logBeginRegex, String regex, IEnumerable<String> key, IEnumerable<String> filterKey, IEnumerable<String> filterRegex,
String topicFormat = null, Boolean preserve = ConfigInputDetailInfo.DefaultPreserve, Int32 preserveDepth = default, String fileEncoding = null, String logSample = null, String project = null)
=> client.CreateConfigAsync(
configName,
"file",
new ConfigInputDetailInfo(logType, logPath, filePattern, localStorage, timeFormat, logBeginRegex, regex, key, filterKey, filterRegex)
{
TopicFormat = topicFormat,
Preserve = preserve,
PreserveDepth = preserveDepth,
FileEncoding = fileEncoding
},
"LogService",
new ConfigOutputDetailInfo(logstoreName),
logSample,
project);
/// <summary>
/// 列出 Project 下所有配置信息,可以通过参数进行翻页。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="offset">返回记录的起始位置,默认为 0。</param>
/// <param name="size">每页返回最大条目,默认 500最大值。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.ListConfigAsync"/>
public static Task<IResponse<ListConfigResult>> ListConfigAsync(this ILogServiceClient client,
Int32 offset = ListConfigRequest.DefaultOffset, Int32 size = ListConfigRequest.DefaultSize, String project = null)
=> client.ListConfigAsync(new ListConfigRequest
{
Offset = offset,
Size = size,
ProjectName = project
});
/// <summary>
/// 列出 config 应用的机器列表。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="configName">日志配置名称。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetAppliedMachineGroupsAsync"/>
public static Task<IResponse<GetAppliedMachineGroupsResult>> GetAppliedMachineGroupsAsync(this ILogServiceClient client,
String configName,
String project = null)
=> client.GetAppliedMachineGroupsAsync(new GetAppliedMachineGroupsRequest(configName)
{
ProjectName = project
});
/// <summary>
/// 获得一个配置的详细信息。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="configName">日志配置名称。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetConfigAsync"/>
public static Task<IResponse<GetConfigResult>> GetConfigAsync(this ILogServiceClient client,
String configName,
String project = null)
=> client.GetConfigAsync(new GetConfigRequest(configName)
{
ProjectName = project
});
/// <summary>
/// 删除特定 config如果 config 已被 应用到机器组,则 Logtail 配置也会被删除。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="configName">日志配置名称。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.DeleteConfigAsync"/>
public static Task<IResponse> DeleteConfigAsync(this ILogServiceClient client,
String configName,
String project = null)
=> client.DeleteConfigAsync(new DeleteConfigRequest(configName)
{
ProjectName = project
});
/// <summary>
/// 更新配置内容,如果配置被应用到机器组,对应机器也会同时更新。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="configName">日志配置名称, Project 下唯一。</param>
/// <param name="inputType">输入类型,现在只支持 file。</param>
/// <param name="inputDetail">输入详情。</param>
/// <param name="outputType">输出类型,现在只支持 LogService。</param>
/// <param name="outputDetail">输出详情。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.UpdateConfigAsync"/>
public static Task<IResponse> UpdateConfigAsync(this ILogServiceClient client,
String configName, String inputType, ConfigInputDetailInfo inputDetail, String outputType, ConfigOutputDetailInfo outputDetail,
String project = null)
=> client.UpdateConfigAsync(new UpdateConfigRequest(configName, inputType, inputDetail, outputType, outputDetail)
{
ProjectName = project
});
#endregion Config
#region Project
/// <summary>
/// 创建project。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="projectName">project的名称全局唯一。</param>
/// <param name="projectDesc">project描述。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.CreateProjectAsync"/>
public static Task<IResponse> CreateProjectAsync(this ILogServiceClient client,
String projectName, String projectDesc)
=> client.CreateProjectAsync(new CreateProjectRequest(projectName, projectDesc));
/// <summary>
/// 获取指定区域Project列表。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="projectName">用于过滤返回结果的project名称支持部分匹配。</param>
/// <param name="offset">请求结果的起始位置默认为0。</param>
/// <param name="size">每次请求返回结果最大数量默认500最大值。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.ListProjectAsync"/>
public static Task<IResponse<ListProjectResult>> ListProjectAsync(this ILogServiceClient client,
String projectName = "", Int32 offset = ListProjectRequest.DefaultOffset, Int32 size = ListProjectRequest.DefaultSize)
=> client.ListProjectAsync(new ListProjectRequest
{
ProjectName = projectName,
Offset = offset,
Size = size
});
/// <summary>
/// 获取当前Project信息。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.GetProjectAsync"/>
public static Task<IResponse<GetProjectResult>> GetProjectAsync(this ILogServiceClient client,
String project = null)
=> client.GetProjectAsync(new GetProjectRequest
{
ProjectName = project
});
/// <summary>
/// 删除当前Project。
/// </summary>
/// <param name="client">client实例。</param>
/// <param name="project">项目名,此参数将覆盖 client 中默认设置。</param>
/// <returns>异步响应结果。</returns>
/// <seealso cref="ILogServiceClient.DeleteProjectAsync"/>
public static Task<IResponse> DeleteProjectAsync(this ILogServiceClient client,
String project = null)
=> client.DeleteProjectAsync(new DeleteProjectRequest
{
ProjectName = project
});
#endregion
}
}

View File

@@ -0,0 +1,64 @@
//
// AssemblyInfo.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using Aliyun.Api.LogService.Properties;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("Aliyun.Api.Log")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Alibaba Cloud")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Copyright (c) 2018 Alibaba Cloud")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.1.1")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]
[assembly: InternalsVisibleTo("Aliyun.Api.LogService.Tests, PublicKey=" + AssemblyInfo.PublicKey)]
namespace Aliyun.Api.LogService.Properties
{
internal static class AssemblyInfo
{
internal const String PublicKey = @"0024000004800000940000000602000000240000525341310004000001000100a726f8dd71d3de90991d084fc20c20e0078a4956f6d66d4f7cc1f0708c967d8053f482ecbeed7bbca78a33186b6be7244b493a04357f68af17c643c4f61ee142e8267d3f197a57268a24212c5436cdb0df54dbf91caa7f3b41702689ece692c0c90a48e5e3ff692766f63689ceae2346ef09e6e938a690e4b3c1dfc43c30938c";
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\netstandard2.0\publish\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<History>False|2022-05-24T13:18:22.0793268Z;False|2022-05-24T21:18:12.0968669+08:00;False|2022-05-24T21:17:41.3515183+08:00;True|2022-05-17T15:01:03.1154849+08:00;True|2022-05-16T16:32:28.4546284+08:00;True|2022-05-16T15:30:11.5553413+08:00;</History>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,107 @@
//
// CommonExtensions.cs
//
// Author:
// MiNG <developer@ming.gz.cn>
//
// Copyright (c) 2018 Alibaba Cloud
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
namespace Aliyun.Api.LogService.Utils
{
internal static class CommonExtensions
{
internal static Boolean IsEmpty(this String source)
{
return String.IsNullOrEmpty(source);
}
internal static Boolean IsNotEmpty(this String source)
{
return !String.IsNullOrEmpty(source);
}
internal static Boolean IsEmpty<T>(this T[] source)
{
return source == null || source.Length == 0;
}
internal static Boolean IsNotEmpty<T>(this T[] source)
{
return source != null && source.Length != 0;
}
internal static Boolean IsEmpty<T>(this IEnumerable<T> source)
{
return source == null || !source.Any();
}
internal static Boolean IsNotEmpty<T>(this IEnumerable<T> source)
{
return source != null && source.Any();
}
internal static IEnumerable<KeyValuePair<String, String>> ToEnumerable(this NameValueCollection source)
{
return source.AllKeys
.SelectMany(key => source.GetValues(key), (key, value) => new KeyValuePair<String, String>(key, value));
}
/// <summary>
/// Freeze the IEnumerable to avoid re-evaluating on <paramref name="source"/>.
/// </summary>
/// <param name="source">The source to freeze.</param>
/// <typeparam name="T">The item type in source.</typeparam>
/// <returns>If source has already frozen, return itself; otherwize <see cref="Enumerable.ToArray{TSource}"/> will be applied.</returns>
internal static IEnumerable<T> Freeze<T>(this IEnumerable<T> source)
{
switch (source)
{
case null:
case Array _:
case ICollection<T> _:
case IReadOnlyCollection<T> _:
{
return source;
}
default:
{
return source.ToArray();
}
}
}
internal static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> source, TKey key)
{
if (source == null)
{
return default;
}
return source.TryGetValue(key, out var value) ? value : default;
}
}
}

Some files were not shown because too many files have changed in this diff Show More