finish data mask strategy

This commit is contained in:
Liujian
2024-11-26 23:44:00 +08:00
parent 651a1de601
commit cb63931f30
36 changed files with 1557 additions and 265 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ type CommonInput struct {
type StatisticInput struct {
Apis []string `json:"apis"`
Projects []string `json:"projects"`
Services []string `json:"services"`
Path string `json:"path"`
*CommonInput
}
+3 -3
View File
@@ -21,12 +21,12 @@ type ApiStatisticBasicItem struct {
*MonCommonData
}
type ProjectStatisticItem struct {
*ProjectStatisticBasicItem
type ServiceStatisticItem struct {
*ServiceStatisticBasicItem
IsRed bool `json:"is_red"` //是否标红
}
type ProjectStatisticBasicItem struct {
type ServiceStatisticBasicItem struct {
Id string `json:"id"` //订阅方ID
Name string `json:"name"` //订阅方名称
*MonCommonData
+447 -11
View File
@@ -5,14 +5,15 @@ import (
"encoding/json"
"errors"
"fmt"
"sort"
"time"
"github.com/APIParkLab/APIPark/gateway"
"github.com/eolinker/eosc/log"
"github.com/eolinker/go-common/auto"
"github.com/eolinker/go-common/store"
"github.com/eolinker/go-common/utils"
"gorm.io/gorm"
"sort"
"time"
"github.com/APIParkLab/APIPark/service/service"
@@ -42,6 +43,442 @@ type imlMonitorStatisticModule struct {
apiService api.IAPIService `autowired:""`
}
func (i *imlMonitorStatisticModule) ApiStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error) {
clusterId := cluster.DefaultClusterID
_, err := i.clusterService.Get(ctx, clusterId)
if err != nil {
return nil, err
}
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, err
}
wm := make(map[string]interface{})
if len(input.Apis) > 0 {
wm["uuid"] = input.Apis
wheres = append(wheres, monitor.MonWhereItem{
Key: "api",
Operation: "in",
Values: input.Apis,
})
}
if len(input.Services) > 0 {
wm["service"] = input.Services
wheres = append(wheres, monitor.MonWhereItem{
Key: "project",
Operation: "in",
Values: input.Services,
})
}
// 查询符合条件的API
apis, err := i.apiService.Search(ctx, input.Path, wm)
if err != nil {
return nil, err
}
if len(apis) < 1 {
// 没有符合条件的API
return make([]*monitor_dto.ApiStatisticBasicItem, 0), nil
}
apiIds := utils.SliceToSlice(apis, func(t *api.API) string {
return t.UUID
})
apiInfos, err := i.apiService.ListInfo(ctx, apiIds...)
if err != nil {
return nil, err
}
return i.apiStatistics(ctx, clusterId, apiInfos, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
}
func (i *imlMonitorStatisticModule) apiStatistics(ctx context.Context, clusterId string, apiInfos []*api.Info, start time.Time, end time.Time, wheres []monitor.MonWhereItem, limit int) ([]*monitor_dto.ApiStatisticBasicItem, error) {
statisticMap, err := i.statistics(ctx, clusterId, "api", start, end, wheres, limit)
if err != nil {
return nil, err
}
result := make([]*monitor_dto.ApiStatisticBasicItem, 0, len(statisticMap))
for _, item := range apiInfos {
statisticItem := &monitor_dto.ApiStatisticBasicItem{
Id: item.UUID,
Name: item.Name,
Path: item.Path,
Service: auto.UUID(item.Service),
MonCommonData: new(monitor_dto.MonCommonData),
}
if val, ok := statisticMap[item.UUID]; ok {
statisticItem.MonCommonData = monitor_dto.ToMonCommonData(val)
delete(statisticMap, item.UUID)
}
result = append(result, statisticItem)
}
for key, item := range statisticMap {
statisticItem := &monitor_dto.ApiStatisticBasicItem{
Id: key,
Name: "未知API-" + key,
MonCommonData: monitor_dto.ToMonCommonData(item),
}
if key == "-" {
statisticItem.Name = "无API"
}
result = append(result, statisticItem)
}
sort.Slice(result, func(i, j int) bool {
return result[i].RequestTotal > result[j].RequestTotal
})
return result, nil
}
func (i *imlMonitorStatisticModule) SubscriberStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
clusterId := cluster.DefaultClusterID
_, err := i.clusterService.Get(ctx, clusterId)
if err != nil {
return nil, err
}
apps, err := i.serviceService.AppList(ctx, input.Services...)
if err != nil {
return nil, err
}
appIds := utils.SliceToSlice(apps, func(p *service.Service) string {
return p.Id
})
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, err
}
if len(appIds) > 0 {
wheres = append(wheres, monitor.MonWhereItem{
Key: "app",
Operation: "in",
Values: appIds,
})
}
return i.serviceStatistics(ctx, clusterId, apps, "app", formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
}
func (i *imlMonitorStatisticModule) serviceStatistics(ctx context.Context, clusterId string, services []*service.Service, groupBy string, start time.Time, end time.Time, wheres []monitor.MonWhereItem, limit int) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
statisticMap, err := i.statistics(ctx, clusterId, groupBy, start, end, wheres, limit)
if err != nil {
return nil, err
}
result := make([]*monitor_dto.ServiceStatisticBasicItem, 0, len(statisticMap))
for _, item := range services {
statisticItem := &monitor_dto.ServiceStatisticBasicItem{
Id: item.Id,
Name: item.Name,
MonCommonData: new(monitor_dto.MonCommonData),
}
if val, ok := statisticMap[item.Id]; ok {
statisticItem.MonCommonData = monitor_dto.ToMonCommonData(val)
delete(statisticMap, item.Id)
}
result = append(result, statisticItem)
}
for key, item := range statisticMap {
statisticItem := &monitor_dto.ServiceStatisticBasicItem{
Id: key,
Name: "未知-" + key,
MonCommonData: monitor_dto.ToMonCommonData(item),
}
if key == "-" {
statisticItem.Name = "-"
}
result = append(result, statisticItem)
}
sort.Slice(result, func(i, j int) bool {
return result[i].RequestTotal > result[j].RequestTotal
})
return result, nil
}
func (i *imlMonitorStatisticModule) ProviderStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
clusterId := cluster.DefaultClusterID
_, err := i.clusterService.Get(ctx, clusterId)
if err != nil {
return nil, err
}
services, err := i.serviceService.ServiceList(ctx, input.Services...)
if err != nil {
return nil, err
}
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, err
}
if len(input.Services) > 0 {
wheres = append(wheres, monitor.MonWhereItem{
Key: "provider",
Operation: "in",
Values: input.Services,
})
}
return i.serviceStatistics(ctx, clusterId, services, "provider", formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
}
func (i *imlMonitorStatisticModule) APITrend(ctx context.Context, apiId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
clusterId := cluster.DefaultClusterID
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, "", err
}
wheres = append(wheres, monitor.MonWhereItem{
Key: "api",
Operation: "=",
Values: []string{apiId},
})
executor, err := i.getExecutor(ctx, clusterId)
if err != nil {
return nil, "", err
}
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
if err != nil {
return nil, "", err
}
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
}
func (i *imlMonitorStatisticModule) ProviderTrend(ctx context.Context, providerId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
clusterId := cluster.DefaultClusterID
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, "", err
}
wheres = append(wheres, monitor.MonWhereItem{
Key: "provider",
Operation: "=",
Values: []string{providerId},
})
executor, err := i.getExecutor(ctx, clusterId)
if err != nil {
return nil, "", err
}
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
if err != nil {
return nil, "", err
}
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
}
func (i *imlMonitorStatisticModule) SubscriberTrend(ctx context.Context, subscriberId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
clusterId := cluster.DefaultClusterID
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, "", err
}
wheres = append(wheres, monitor.MonWhereItem{
Key: "app",
Operation: "=",
Values: []string{subscriberId},
})
executor, err := i.getExecutor(ctx, clusterId)
if err != nil {
return nil, "", err
}
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
if err != nil {
return nil, "", err
}
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
}
func (i *imlMonitorStatisticModule) InvokeTrendWithSubscriberAndApi(ctx context.Context, apiId string, subscriberId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
clusterId := cluster.DefaultClusterID
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, "", err
}
wheres = append(wheres, monitor.MonWhereItem{
Key: "api",
Operation: "=",
Values: []string{apiId},
}, monitor.MonWhereItem{
Key: "app",
Operation: "=",
Values: []string{subscriberId},
})
executor, err := i.getExecutor(ctx, clusterId)
if err != nil {
return nil, "", err
}
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
if err != nil {
return nil, "", err
}
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
}
func (i *imlMonitorStatisticModule) InvokeTrendWithProviderAndApi(ctx context.Context, providerId string, apiId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
clusterId := cluster.DefaultClusterID
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, "", err
}
wheres = append(wheres, monitor.MonWhereItem{
Key: "api",
Operation: "=",
Values: []string{apiId},
}, monitor.MonWhereItem{
Key: "provider",
Operation: "=",
Values: []string{providerId},
})
executor, err := i.getExecutor(ctx, clusterId)
if err != nil {
return nil, "", err
}
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
if err != nil {
return nil, "", err
}
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
}
func (i *imlMonitorStatisticModule) statisticOnApi(ctx context.Context, clusterId string, apiId string, groupBy string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
_, err := i.clusterService.Get(ctx, clusterId)
if err != nil {
return nil, err
}
var service []*service.Service
switch groupBy {
case "app":
service, err = i.serviceService.AppList(ctx)
case "provider":
service, err = i.serviceService.ServiceList(ctx)
default:
return nil, errors.New("invalid group by")
}
if err != nil {
return nil, err
}
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, err
}
wheres = append(wheres, monitor.MonWhereItem{
Key: "api",
Operation: "=",
Values: []string{apiId},
})
statisticMap, err := i.statistics(ctx, clusterId, groupBy, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
if err != nil {
return nil, err
}
result := make([]*monitor_dto.ServiceStatisticBasicItem, 0, len(statisticMap))
for _, item := range service {
statisticItem := &monitor_dto.ServiceStatisticBasicItem{
Id: item.Id,
Name: item.Name,
MonCommonData: new(monitor_dto.MonCommonData),
}
if val, ok := statisticMap[item.Id]; ok {
statisticItem.MonCommonData = monitor_dto.ToMonCommonData(val)
delete(statisticMap, item.Id)
}
result = append(result, statisticItem)
}
for key, item := range statisticMap {
statisticItem := &monitor_dto.ServiceStatisticBasicItem{
Id: key,
Name: "未知-" + key,
MonCommonData: monitor_dto.ToMonCommonData(item),
}
if key == "-" {
statisticItem.Name = "-"
}
result = append(result, statisticItem)
}
sort.Slice(result, func(i, j int) bool {
return result[i].RequestTotal > result[j].RequestTotal
})
return result, nil
}
func (i *imlMonitorStatisticModule) ProviderStatisticsOnApi(ctx context.Context, apiId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
clusterId := cluster.DefaultClusterID
return i.statisticOnApi(ctx, clusterId, apiId, "provider", input)
}
func (i *imlMonitorStatisticModule) ApiStatisticsOnProvider(ctx context.Context, providerId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error) {
clusterId := cluster.DefaultClusterID
_, err := i.clusterService.Get(ctx, clusterId)
if err != nil {
return nil, err
}
apiInfos, err := i.apiService.ListInfoForService(ctx, providerId)
if err != nil {
return nil, err
}
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, err
}
wheres = append(wheres, monitor.MonWhereItem{
Key: "provider",
Operation: "=",
Values: []string{providerId},
})
return i.apiStatistics(ctx, clusterId, apiInfos, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
}
func (i *imlMonitorStatisticModule) ApiStatisticsOnSubscriber(ctx context.Context, subscriberId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error) {
clusterId := cluster.DefaultClusterID
_, err := i.clusterService.Get(ctx, clusterId)
if err != nil {
return nil, err
}
// 根据订阅ID查询订阅的服务列表
subscriptions, err := i.subscribeService.MySubscribeServices(ctx, subscriberId, nil)
if err != nil {
return nil, err
}
serviceIds := utils.SliceToSlice(subscriptions, func(t *subscribe.Subscribe) string {
return t.Service
})
if len(serviceIds) < 1 {
return nil, nil
}
apiInfos, err := i.apiService.ListInfoForServices(ctx, serviceIds...)
if err != nil {
return nil, err
}
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, err
}
wheres = append(wheres, monitor.MonWhereItem{
Key: "app",
Operation: "=",
Values: []string{subscriberId},
})
return i.apiStatistics(ctx, clusterId, apiInfos, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
}
func (i *imlMonitorStatisticModule) SubscriberStatisticsOnApi(ctx context.Context, apiId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
clusterId := cluster.DefaultClusterID
return i.statisticOnApi(ctx, clusterId, apiId, "app", input)
}
func (i *imlMonitorStatisticModule) MessageTrend(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonMessageTrend, string, error) {
clusterId := cluster.DefaultClusterID
wheres, err := i.genCommonWheres(ctx, clusterId)
@@ -173,7 +610,7 @@ func (i *imlMonitorStatisticModule) TopAPIStatistics(ctx context.Context, limit
}
func (i *imlMonitorStatisticModule) TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error) {
func (i *imlMonitorStatisticModule) TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error) {
clusterId := cluster.DefaultClusterID
_, err := i.clusterService.Get(ctx, clusterId)
if err != nil {
@@ -182,7 +619,7 @@ func (i *imlMonitorStatisticModule) TopSubscriberStatistics(ctx context.Context,
return i.topProjectStatistics(ctx, clusterId, "app", input, limit)
}
func (i *imlMonitorStatisticModule) TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error) {
func (i *imlMonitorStatisticModule) TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error) {
clusterId := cluster.DefaultClusterID
_, err := i.clusterService.Get(ctx, clusterId)
if err != nil {
@@ -191,12 +628,12 @@ func (i *imlMonitorStatisticModule) TopProviderStatistics(ctx context.Context, l
return i.topProjectStatistics(ctx, clusterId, "provider", input, limit)
}
func (i *imlMonitorStatisticModule) topProjectStatistics(ctx context.Context, partitionId string, groupBy string, input *monitor_dto.CommonInput, limit int) ([]*monitor_dto.ProjectStatisticItem, error) {
wheres, err := i.genCommonWheres(ctx, partitionId)
func (i *imlMonitorStatisticModule) topProjectStatistics(ctx context.Context, clusterId string, groupBy string, input *monitor_dto.CommonInput, limit int) ([]*monitor_dto.ServiceStatisticItem, error) {
wheres, err := i.genCommonWheres(ctx, clusterId)
if err != nil {
return nil, err
}
statisticMap, err := i.statistics(ctx, partitionId, groupBy, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, limit)
statisticMap, err := i.statistics(ctx, clusterId, groupBy, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, limit)
if err != nil {
return nil, err
}
@@ -216,10 +653,10 @@ func (i *imlMonitorStatisticModule) topProjectStatistics(ctx context.Context, pa
return t.Id
})
result := make([]*monitor_dto.ProjectStatisticItem, 0, len(statisticMap))
result := make([]*monitor_dto.ServiceStatisticItem, 0, len(statisticMap))
for key, item := range statisticMap {
statisticItem := &monitor_dto.ProjectStatisticItem{
ProjectStatisticBasicItem: &monitor_dto.ProjectStatisticBasicItem{
statisticItem := &monitor_dto.ServiceStatisticItem{
ServiceStatisticBasicItem: &monitor_dto.ServiceStatisticBasicItem{
Id: key,
MonCommonData: monitor_dto.ToMonCommonData(item),
},
@@ -407,7 +844,6 @@ func (m *imlMonitorConfig) GetMonitorConfig(ctx context.Context) (*monitor_dto.M
Driver: info.Driver,
Config: cfg,
}, nil
return nil, nil
}
func (m *imlMonitorConfig) GetMonitorCluster(ctx context.Context) ([]*monitor_dto.MonitorCluster, error) {
+22 -4
View File
@@ -13,18 +13,36 @@ import (
type IMonitorStatisticModule interface {
TopAPIStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ApiStatisticItem, error)
TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error)
TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error)
TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error)
TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error)
// RequestSummary 请求概况
RequestSummary(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonSummaryOutput, error)
// ProxySummary 转发概况
ProxySummary(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonSummaryOutput, error)
// InvokeTrend 调用次数趋势
InvokeTrend(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
// MessageTrend 消息趋势
MessageTrend(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonMessageTrend, string, error)
ApiStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error)
SubscriberStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error)
ProviderStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error)
APITrend(ctx context.Context, apiId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
ProviderTrend(ctx context.Context, providerId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
SubscriberTrend(ctx context.Context, subscriberId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
InvokeTrendWithSubscriberAndApi(ctx context.Context, apiId string, subscriberId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
InvokeTrendWithProviderAndApi(ctx context.Context, providerId string, apiId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
ProviderStatisticsOnApi(ctx context.Context, apiId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error)
ApiStatisticsOnProvider(ctx context.Context, providerId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error)
ApiStatisticsOnSubscriber(ctx context.Context, subscriberId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error)
SubscriberStatisticsOnApi(ctx context.Context, apiId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error)
}
type IMonitorConfigModule interface {
+2 -1
View File
@@ -26,7 +26,8 @@ type Item struct {
type SimpleItem struct {
Id string `json:"id"`
Methods []string `json:"methods"`
Path string `json:"request_path"`
//Name string `json:"name"`
Path string `json:"request_path"`
}
type Detail struct {
+112
View File
@@ -0,0 +1,112 @@
package router
import (
"context"
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
"github.com/eolinker/go-common/utils"
"github.com/eolinker/eosc/log"
"github.com/APIParkLab/APIPark/service/api"
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
)
var _ strategy_filter.IRemoteFilter = (*imlRouterFilter)(nil)
type imlRouterFilter struct {
service api.IAPIService `autowired:""`
}
func (i *imlRouterFilter) Name() string {
return "api"
}
func (i *imlRouterFilter) Title() string {
return "API"
}
func (i *imlRouterFilter) Labels(values ...string) []string {
list, err := i.service.ListInfo(context.Background(), values...)
if err != nil {
log.Errorf("get api labels error: %v", err)
return nil
}
return utils.SliceToSlice(list, func(a *api.Info) string {
return a.Name
})
}
func (i *imlRouterFilter) Type() string {
return strategy_filter.TypeRemote
}
func (i *imlRouterFilter) Scopes() []string {
return []string{
//strategy_filter.ScopeGlobal,
strategy_filter.ScopeService,
}
}
func (i *imlRouterFilter) Option() *strategy_filter.Option {
return &strategy_filter.Option{
Name: i.Name(),
Title: i.Title(),
Type: i.Type(),
}
}
func (i *imlRouterFilter) Titles() []strategy_filter.OptionTitle {
return []strategy_filter.OptionTitle{
{
Field: "name",
Title: "api name",
},
{
Field: "methods",
Title: "methods",
},
{
Field: "request_path",
Title: "request path",
},
}
}
func (i *imlRouterFilter) Key() string {
return "id"
}
func (i *imlRouterFilter) Target() string {
return "list"
}
func (i *imlRouterFilter) RemoteList(ctx context.Context, keyword string, condition map[string]interface{}, page int, pageSize int) ([]any, int64, error) {
if pageSize == -1 {
// 获取全部
list, err := i.service.Search(ctx, keyword, condition)
if err != nil {
return nil, 0, err
}
return utils.SliceToSlice(list, func(s *api.API) any {
return &router_dto.SimpleItem{
Id: s.UUID,
Path: s.Path,
Methods: s.Method,
}
}), int64(len(list)), nil
}
list, total, err := i.service.SearchByPage(ctx, keyword, condition, page, pageSize, "update_at")
if err != nil {
return nil, 0, err
}
return utils.SliceToSlice(list, func(s *api.API) any {
return &router_dto.SimpleItem{
Id: s.UUID,
Path: s.Path,
Methods: s.Method,
}
}), total, nil
}
+7 -1
View File
@@ -2,9 +2,11 @@ package router
import (
"context"
"github.com/APIParkLab/APIPark/module/system"
"reflect"
"github.com/APIParkLab/APIPark/module/system"
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
"github.com/eolinker/go-common/autowire"
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
@@ -45,4 +47,8 @@ func init() {
autowire.Auto[IExportRouterModule](func() reflect.Value {
return reflect.ValueOf(apiModule)
})
filter := new(imlRouterFilter)
autowire.Autowired(filter)
strategy_filter.RegisterRemoteFilter(filter)
}
+125
View File
@@ -0,0 +1,125 @@
package service
import (
"context"
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
"github.com/eolinker/go-common/auto"
"github.com/APIParkLab/APIPark/service/service"
"github.com/eolinker/eosc/log"
"github.com/eolinker/go-common/utils"
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
)
var _ strategy_filter.IRemoteFilter = (*imlAppFilter)(nil)
type imlAppFilter struct {
service service.IServiceService `autowired:""`
}
func (i *imlAppFilter) Name() string {
return "application"
}
func (i *imlAppFilter) Title() string {
return "消费者"
}
func (i *imlAppFilter) Labels(values ...string) []string {
if len(values) == 0 {
return nil
}
if values[0] == strategy_filter.ValuesALL {
return []string{
"全部消费者",
}
}
apps, err := i.service.AppList(context.Background(), values...)
if err != nil {
log.Error(err)
return nil
}
return utils.SliceToSlice(apps, func(a *service.Service) string {
return a.Name
})
}
func (i *imlAppFilter) Type() string {
return strategy_filter.TypeRemote
}
func (i *imlAppFilter) Scopes() []string {
return []string{
strategy_filter.ScopeGlobal,
strategy_filter.ScopeService,
}
}
func (i *imlAppFilter) Option() *strategy_filter.Option {
return &strategy_filter.Option{
Name: i.Name(),
Title: i.Title(),
Type: i.Type(),
}
}
func (i *imlAppFilter) Titles() []strategy_filter.OptionTitle {
return []strategy_filter.OptionTitle{
{
Field: "name",
Title: "consumer",
},
{
Field: "id",
Title: "consumer id",
},
{
Field: "description",
Title: "description",
},
}
}
func (i *imlAppFilter) Key() string {
return "id"
}
func (i *imlAppFilter) Target() string {
return "list"
}
func (i *imlAppFilter) RemoteList(ctx context.Context, keyword string, condition map[string]interface{}, page int, pageSize int) ([]any, int64, error) {
if condition == nil {
condition = make(map[string]interface{})
}
condition["as_app"] = true
if pageSize == -1 {
// 获取全部
list, err := i.service.Search(ctx, keyword, condition, "update_at")
if err != nil {
return nil, 0, err
}
return utils.SliceToSlice(list, func(s *service.Service) any {
return &service_dto.SimpleAppItem{
Id: s.Id,
Name: s.Name,
Team: auto.UUID(s.Team),
Description: s.Description,
}
}), int64(len(list)), nil
}
list, total, err := i.service.SearchByPage(ctx, keyword, condition, page, pageSize, "update_at")
if err != nil {
return nil, 0, err
}
return utils.SliceToSlice(list, func(s *service.Service) any {
return &service_dto.SimpleAppItem{
Id: s.Id,
Name: s.Name,
Team: auto.UUID(s.Team),
Description: s.Description,
}
}), total, nil
}
+42 -44
View File
@@ -109,9 +109,7 @@ func (i *imlServiceModule) ExportAll(ctx context.Context) ([]*service_dto.Export
Catalogue: s.Catalogue,
Logo: s.Logo,
}
//if v, ok := docMap[s.Id]; ok {
// info.Doc = v.Doc
//}
if tags, ok := serviceTagMap[s.Id]; ok {
info.Tags = tags
}
@@ -191,47 +189,47 @@ func (i *imlServiceModule) SearchMyServices(ctx context.Context, teamId string,
// }), nil
//}
//func (i *imlServiceModule) Simple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
// w := make(map[string]interface{})
// w["as_server"] = true
//
// services, err := i.serviceService.Search(ctx, keyword, w)
// if err != nil {
// return nil, err
// }
//
// items := make([]*service_dto.SimpleServiceItem, 0, len(services))
// for _, p := range services {
//
// items = append(items, &service_dto.SimpleServiceItem{
// Id: p.Id,
// Name: p.Name,
// Description: p.Description,
// Team: auto.UUID(p.Team),
// })
// }
// return items, nil
//}
//
//func (i *imlServiceModule) MySimple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
// services, err := i.searchMyServices(ctx, "", keyword)
//
// if err != nil {
// return nil, err
// }
//
// items := make([]*service_dto.SimpleServiceItem, 0, len(services))
// for _, p := range services {
//
// items = append(items, &service_dto.SimpleServiceItem{
// Id: p.Id,
// Name: p.Name,
// Description: p.Description,
// Team: auto.UUID(p.Team),
// })
// }
// return items, nil
//}
func (i *imlServiceModule) Simple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error) {
w := make(map[string]interface{})
w["as_server"] = true
services, err := i.serviceService.Search(ctx, "", w)
if err != nil {
return nil, err
}
items := make([]*service_dto.SimpleServiceItem, 0, len(services))
for _, p := range services {
items = append(items, &service_dto.SimpleServiceItem{
Id: p.Id,
Name: p.Name,
Description: p.Description,
Team: auto.UUID(p.Team),
})
}
return items, nil
}
func (i *imlServiceModule) MySimple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error) {
services, err := i.searchMyServices(ctx, "", "")
if err != nil {
return nil, err
}
items := make([]*service_dto.SimpleServiceItem, 0, len(services))
for _, p := range services {
items = append(items, &service_dto.SimpleServiceItem{
Id: p.Id,
Name: p.Name,
Description: p.Description,
Team: auto.UUID(p.Team),
})
}
return items, nil
}
func (i *imlServiceModule) Get(ctx context.Context, id string) (*service_dto.Service, error) {
now := time.Now()
+10 -4
View File
@@ -4,6 +4,8 @@ import (
"context"
"reflect"
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
"github.com/APIParkLab/APIPark/module/system"
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
@@ -25,11 +27,11 @@ type IServiceModule interface {
// Delete 删除项目
Delete(ctx context.Context, id string) error
// Simple 获取简易项目列表
//Simple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error)
//Simple 获取简易项目列表
Simple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error)
// MySimple 获取我的简易项目列表
//MySimple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error)
//MySimple 获取我的简易项目列表
MySimple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error)
}
type IServiceDocModule interface {
@@ -83,4 +85,8 @@ func init() {
return reflect.ValueOf(serviceDocModule)
})
filter := new(imlAppFilter)
autowire.Autowired(filter)
strategy_filter.RegisterRemoteFilter(filter)
}
-132
View File
@@ -1,132 +0,0 @@
package strategy_driver
import (
"fmt"
"regexp"
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
)
type FilterOptionsItem struct {
Name string
Title string
Type string
Pattern *regexp.Regexp
Options []string
}
const (
FilterMethod = "method"
FilterPath = "path"
FilterIP = "ip"
FilterApplication = "application"
FilterApi = "api"
FilterService = "service"
FilterAppKey = "appkey"
FilterTypeRemote = "remote"
FilterTypePattern = "pattern"
FilterTypeStatic = "static"
FilterValuesALL = "ALL"
)
const (
ApiPathRegexp = `^\*?[\w-/]+\*?$`
CIDRIpv4Exp = `^(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([1-9]|[1-2]\d|3[0-2]))?$`
)
const (
HttpALL = "ALL"
HttpGET = "GET"
HttpPOST = "POST"
HttpPUT = "PUT"
HttpDELETE = "DELETE"
HttpPATCH = "PATCH"
HttpHEADER = "HEADER"
HttpOPTIONS = "OPTIONS"
)
var (
staticOptions = []*FilterOptionsItem{
{
Name: FilterMethod,
Title: "API请求方式",
Type: FilterTypeStatic,
Options: []string{HttpALL, HttpGET, HttpPOST, HttpPUT, HttpDELETE, HttpPATCH, HttpHEADER, HttpOPTIONS},
}, {
Name: FilterPath,
Title: "API路径",
Type: FilterTypePattern,
Pattern: regexp.MustCompile(ApiPathRegexp),
}, {
Name: FilterIP,
Title: "IP",
Type: FilterTypePattern,
Pattern: regexp.MustCompile(CIDRIpv4Exp),
},
}
globalFilters = map[string]struct{}{}
serviceFilters = map[string]struct{}{}
)
func init() {
for _, option := range staticOptions {
globalFilters[option.Name] = struct{}{}
}
for _, option := range staticOptions {
serviceFilters[option.Name] = struct{}{}
}
}
func CheckFilters(name string, scope strategy_dto.Scope, filters []*strategy_dto.Filter) error {
var fs map[string]struct{}
switch scope.String() {
case strategy_dto.ScopeSystem:
fs = globalFilters
case strategy_dto.ScopeService:
fs = serviceFilters
default:
return fmt.Errorf("unknown scope %s", scope)
}
filterNameSet := make(map[string]struct{})
for _, filter := range filters {
_, ok := fs[filter.Name]
if !ok {
return fmt.Errorf("%s filter %s not found", name, filter.Name)
}
if len(filter.Values) == 0 {
return fmt.Errorf("%s.Options can't be null. filter.Name:%s ", name, filter.Name)
}
if _, has := filterNameSet[filter.Name]; has {
return fmt.Errorf("%s.Name %s is reduplicative. ", name, filter.Name)
}
filterNameSet[filter.Name] = struct{}{}
}
return nil
}
type OptionTitle struct {
Field string `json:"field"`
Title string `json:"title" aoi18n:""`
}
type FilterOptionConfig struct {
Title string
Titles []OptionTitle
Key string
}
type IFilterOptionHandler interface {
Name() string
Config() FilterOptionConfig
GetOptions(keyword, conditions map[string]interface{}, pageNum, pageSize int) ([]any, int)
Labels(values ...string) []string
Label(value string) string
}
type IFilterFactory interface {
GetHandler(name string) IFilterOptionHandler
}
+4 -4
View File
@@ -1,7 +1,7 @@
package strategy_dto
const (
ScopeSystem = "system"
ScopeGlobal = "global"
ScopeTeam = "team"
ScopeService = "service"
@@ -16,13 +16,13 @@ type Scope int
func (s Scope) String() string {
switch s {
case 0:
return ScopeSystem
return ScopeGlobal
case 1:
return ScopeTeam
case 2:
return ScopeService
default:
return ScopeSystem
return ScopeGlobal
}
}
@@ -32,7 +32,7 @@ func (s Scope) Int() int {
func ToScope(s string) Scope {
switch s {
case ScopeSystem:
case ScopeGlobal:
return 0
case ScopeTeam:
return 1
+44 -3
View File
@@ -2,12 +2,13 @@ package strategy_dto
import (
"encoding/json"
"time"
"github.com/APIParkLab/APIPark/service/strategy"
"github.com/eolinker/go-common/auto"
)
func ToStrategyItem(s *strategy.Strategy, publishVersion string) *StrategyItem {
func StrategyStatus(s *strategy.Strategy, publishVersion string) string {
publishStatus := PublishStatusOffline
if publishVersion != "" {
if s.IsDelete {
@@ -21,17 +22,36 @@ func ToStrategyItem(s *strategy.Strategy, publishVersion string) *StrategyItem {
}
}
}
return publishStatus
}
func ToStrategyItem(s *strategy.Strategy, publishVersion string, filters string) *StrategyItem {
publishStatus := PublishStatusOffline
if publishVersion != "" {
if s.IsDelete {
publishStatus = PublishStatusDelete
} else {
version := s.UpdateAt.Format("20060102150405")
if version != publishVersion {
publishStatus = PublishStatusUpdate
} else {
publishStatus = PublishStatusOnline
}
}
}
return &StrategyItem{
Id: s.Id,
Name: s.Name,
Priority: 0,
Priority: s.Priority,
Desc: s.Desc,
Filters: "",
Filters: filters,
Updater: auto.UUID(s.Updater),
UpdateTime: auto.TimeLabel(s.UpdateAt),
ProcessedTotal: 0,
PublishStatus: publishStatus,
IsStop: s.IsStop,
IsDelete: s.IsDelete,
}
}
@@ -70,4 +90,25 @@ type StrategyItem struct {
ProcessedTotal int `json:"processed_total"`
PublishStatus string `json:"publish_status"`
IsStop bool `json:"is_stop"`
IsDelete bool `json:"is_delete"`
}
type FilterOption struct {
Name string `json:"name"`
Title string `json:"title"`
Type string `json:"type"`
Pattern string `json:"pattern"`
Options []string `json:"options"`
}
type Title struct {
Field string `json:"field"`
Title string `json:"title" aoi18n:""`
}
type ToPublishItem struct {
Name string `json:"name"`
Priority int `json:"priority"`
Status string `json:"status"`
OptTime time.Time `json:"opt_time"`
}
+71 -6
View File
@@ -3,7 +3,15 @@ package strategy
import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"gorm.io/gorm"
"github.com/eolinker/eosc/log"
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
"github.com/eolinker/go-common/store"
@@ -27,6 +35,34 @@ type imlStrategyModule struct {
transaction store.ITransaction `autowired:""`
}
func (i *imlStrategyModule) ToPublish(ctx context.Context, driver string) ([]*strategy_dto.ToPublishItem, error) {
scope := strategy_dto.ToScope(strategy_dto.ScopeGlobal)
list, err := i.strategyService.SearchAll(ctx, "", driver, scope.Int(), "")
if err != nil {
return nil, err
}
strategyIds := utils.SliceToSlice(list, func(l *strategy.Strategy) string { return l.Id })
commits, err := i.strategyService.ListLatestStrategyCommit(ctx, scope.String(), "", strategyIds...)
if err != nil {
return nil, err
}
commitMap := utils.SliceToMapO(commits, func(c *commit.Commit[strategy.StrategyCommit]) (string, string) { return c.Key, c.Data.Version })
items := make([]*strategy_dto.ToPublishItem, 0, len(list))
for _, l := range list {
status := strategy_dto.StrategyStatus(l, commitMap[l.Id])
if status == strategy_dto.PublishStatusOnline {
continue
}
items = append(items, &strategy_dto.ToPublishItem{
Name: l.Name,
Priority: l.Priority,
Status: status,
OptTime: l.UpdateAt,
})
}
return items, nil
}
func (i *imlStrategyModule) Search(ctx context.Context, keyword string, driver string, scope strategy_dto.Scope, target string, page int, pageSize int, filters []string, order ...string) ([]*strategy_dto.StrategyItem, int64, error) {
list, total, err := i.strategyService.Search(ctx, keyword, driver, scope.Int(), target, page, pageSize, filters, order...)
if err != nil {
@@ -40,7 +76,19 @@ func (i *imlStrategyModule) Search(ctx context.Context, keyword string, driver s
commitMap := utils.SliceToMapO(commits, func(c *commit.Commit[strategy.StrategyCommit]) (string, string) { return c.Key, c.Data.Version })
items := make([]*strategy_dto.StrategyItem, 0, len(list))
for _, l := range list {
item := strategy_dto.ToStrategyItem(l, commitMap[l.Id])
fs := make([]*strategy_dto.Filter, 0)
json.Unmarshal([]byte(l.Filters), &fs)
filterList := make([]string, 0, len(fs))
for _, f := range fs {
info, err := strategy_filter.FilterLabel(f.Name, f.Values)
if err != nil {
log.Errorf("get filter label error: %v", err)
continue
}
filterList = append(filterList, fmt.Sprintf("[%s:%s]", info.Title, info.Label))
}
item := strategy_dto.ToStrategyItem(l, commitMap[l.Id], strings.Join(filterList, ";"))
items = append(items, item)
}
return items, total, nil
@@ -51,7 +99,17 @@ func (i *imlStrategyModule) Get(ctx context.Context, id string) (*strategy_dto.S
if err != nil {
return nil, err
}
return strategy_dto.ToStrategy(info), nil
s := strategy_dto.ToStrategy(info)
for _, f := range s.Filters {
ff, has := strategy_filter.FilterGet(f.Name)
if !has {
return nil, fmt.Errorf("filter not found: %s", f.Name)
}
f.Title = ff.Title()
f.Type = ff.Type()
f.Label = strings.Join(ff.Labels(f.Values...), ",")
}
return s, nil
}
func (i *imlStrategyModule) Create(ctx context.Context, input *strategy_dto.Create) error {
@@ -65,7 +123,7 @@ func (i *imlStrategyModule) Create(ctx context.Context, input *strategy_dto.Crea
if input.Priority < 1 {
input.Priority = 1000
}
err := strategy_driver.CheckFilters(input.Driver, input.Scope, input.Filters)
err := strategy_filter.CheckFilters(input.Driver, input.Scope, input.Filters)
if err != nil {
return err
}
@@ -102,7 +160,7 @@ func (i *imlStrategyModule) Edit(ctx context.Context, id string, input *strategy
}
filters := info.Filters
if input.Filters != nil {
err = strategy_driver.CheckFilters(info.Driver, strategy_dto.Scope(info.Scope), *input.Filters)
err = strategy_filter.CheckFilters(info.Driver, strategy_dto.Scope(info.Scope), *input.Filters)
if err != nil {
return err
}
@@ -138,8 +196,8 @@ func (i *imlStrategyModule) Disable(ctx context.Context, id string) error {
return i.strategyService.Save(ctx, id, &strategy.Edit{IsStop: &stop})
}
func (i *imlStrategyModule) Publish(ctx context.Context, scope string, target string) error {
list, err := i.strategyService.AllByScope(ctx, strategy_dto.ToScope(scope).Int(), target)
func (i *imlStrategyModule) Publish(ctx context.Context, driver string, scope string, target string) error {
list, err := i.strategyService.AllByScope(ctx, driver, strategy_dto.ToScope(scope).Int(), target)
if err != nil {
return err
}
@@ -163,5 +221,12 @@ func (i *imlStrategyModule) Publish(ctx context.Context, scope string, target st
}
func (i *imlStrategyModule) Delete(ctx context.Context, id string) error {
_, err := i.strategyService.LatestStrategyCommit(ctx, strategy_dto.ScopeGlobal, "", id)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
return i.strategyService.Delete(ctx, id)
}
return i.strategyService.SortDelete(ctx, id)
}
+2 -1
View File
@@ -17,8 +17,9 @@ type IStrategyModule interface {
Edit(ctx context.Context, id string, i *strategy_dto.Edit) error
Enable(ctx context.Context, id string) error
Disable(ctx context.Context, id string) error
Publish(ctx context.Context, scope string, target string) error
Publish(ctx context.Context, driver string, scope string, target string) error
Delete(ctx context.Context, id string) error
ToPublish(ctx context.Context, driver string) ([]*strategy_dto.ToPublishItem, error)
}
func init() {
+1
View File
@@ -7,6 +7,7 @@ import (
type InputSetting struct {
InvokeAddress string `json:"invoke_address" key:"system.node.invoke_address"`
SitePrefix string `json:"site_prefix" key:"system.setting.site_prefix"`
}
func (i *InputSetting) Validate() error {
+1
View File
@@ -7,6 +7,7 @@ import (
type Setting struct {
InvokeAddress string `json:"invoke_address" key:"system.node.invoke_address"`
SitePrefix string `json:"site_prefix" key:"system.setting.site_prefix"`
}
func MapStringToStruct[T any](m map[string]string) *T {