Open jobsLee-lcj opened 3 months ago
可以看看cover.out中collection/collection.go的原始数据,看看具体是哪些范围没有覆盖。 另外,你是在window还是mac上测试的?
可以看看cover.out中collection/collection.go的原始数据,看看具体是哪些范围没有覆盖。 另外,你是在window还是mac上测试的?
cover.out原始文件都是有覆盖的,通过go tool cover -html=cover.out
渲染没有问题。看起来可能是前端渲染的问题。我是mac系统。
可以将cover.out中这个文件相关的行贴出来吗? 以及这个文件的代码,如果不方便,可以使用x替代所有的字母。
抱歉回复有些迟,cover.out中collection相关行如下(我怀疑过可能是目录collection和collection/collection.go文件同名导致,所以把文件名称改为了collect.go, 但问题依旧存在):
testops/pkg/service/collection/collect.go:21.67,34.26 5 0 testops/pkg/service/collection/collect.go:34.26,35.24 1 0 testops/pkg/service/collection/collect.go:35.24,38.4 2 0 testops/pkg/service/collection/collect.go:40.2,42.49 3 0 testops/pkg/service/collection/collect.go:67.105,72.16 4 1 testops/pkg/service/collection/collect.go:72.16,76.3 3 1 testops/pkg/service/collection/collect.go:78.2,79.16 2 1 testops/pkg/service/collection/collect.go:79.16,83.3 3 1 testops/pkg/service/collection/collect.go:84.2,86.42 3 1 testops/pkg/service/collection/collect.go:86.42,88.37 2 1 testops/pkg/service/collection/collect.go:88.37,90.43 1 1 testops/pkg/service/collection/collect.go:90.43,92.40 2 1 testops/pkg/service/collection/collect.go:92.40,96.6 3 1 testops/pkg/service/collection/collect.go:97.5,97.10 1 1 testops/pkg/service/collection/collect.go:101.3,101.18 1 1 testops/pkg/service/collection/collect.go:101.18,103.4 1 1 testops/pkg/service/collection/collect.go:106.2,106.29 1 1 testops/pkg/service/collection/collect.go:106.29,108.17 2 1
@jobsLee-lcj 源代码呢?
package collection
import (
"context"
"fmt"
"sync"
"time"
"go.uber.org/zap"
"testops/pkg/service/cloud"
"testops/pkg/store"
"testops/pkg/utils"
"testops/infra/cat-go/cat"
"testops/infra/go-utils/log"
)
// Collector 采集器方法类型
type Collector func(ctx context.Context, s cloud.CloudService) error
func CollectAllIAMData(ctx context.Context, s cloud.CloudService) {
start := time.Now()
funcs := []Collector{
CollectIAMUsers,
}
var wg sync.WaitGroup
wg.Add(len(funcs))
for _, f := range funcs {
go func(f Collector) {
defer wg.Done()
_ = f(ctx, s)
}(f)
}
wg.Wait()
log.Warn(fmt.Sprintf("[CollectAllIAMData] finished,cloudProvider:[%s],cost:[%.1f]s.", s.GetCloudProvider(), time.Since(start).Seconds()), zap.Any("cost", time.Since(start).String()), utils.ZapTraceIdField(ctx))
}
type identity interface {
GetId() uint64
SetId(id uint64)
}
type CollectIAMDateTemplate[T identity] struct {
// 获取数据库数据列表
listDbData func(ctx context.Context, s cloud.CloudService) ([]T, error)
// 获取云上数据列表
listCloudData func(ctx context.Context, s cloud.CloudService) ([]T, error)
// 判断是否相同对象
isSameIdentity func(cloudData T, dbData T) bool
// 判断是否需要更新
needUpdate func(cloudData T, dbData T) bool
// 批量插入数据库
batchInsertDb func(ctx context.Context, data []T) error
// 批量更新数据库
batchUpdateDb func(ctx context.Context, data []T) error
// 删除数据库数据
deleteDb func(ctx context.Context, data T) error
}
func (c *CollectIAMDateTemplate[T]) Run(ctx context.Context, s cloud.CloudService, action string) error {
start := time.Now()
log.Info("start to collect "+action, utils.ZapTraceIdField(ctx))
// 获取数据库数据列表
dbDataList, err := c.listDbData(ctx, s)
if err != nil {
log.Error("list db data failed "+action, zap.Error(err), utils.ZapTraceIdField(ctx))
cat.LogError(err, string(s.GetCloudProvider()))
return err
}
// 获取云上数据列表
cloudDataList, err := c.listCloudData(ctx, s)
if err != nil {
log.Error("list cloud data failed "+action, zap.Error(err), utils.ZapTraceIdField(ctx))
cat.LogError(err, string(s.GetCloudProvider()))
return err
}
var needInsertData []T
var needUpdateData []T
for _, cloudData := range cloudDataList {
existsInDb := false
for _, dbData := range dbDataList {
// 数据库存在,则判断是否更新
if c.isSameIdentity(cloudData, dbData) {
existsInDb = true
if c.needUpdate(cloudData, dbData) {
log.Info("need update "+action, zap.Any("diff", store.DiffStruct(dbData, cloudData)), utils.ZapTraceIdField(ctx))
cloudData.SetId(dbData.GetId())
needUpdateData = append(needUpdateData, cloudData)
}
break
}
}
// 数据库不存在,则插入
if !existsInDb {
needInsertData = append(needInsertData, cloudData)
}
}
// 批量插入
if len(needInsertData) > 0 {
err = c.batchInsertDb(ctx, needInsertData)
if err != nil {
log.Error("BatchInsertDb failed "+action, zap.Any("needInsertSize", len(needInsertData)), zap.Error(err), utils.ZapTraceIdField(ctx))
cat.LogError(err, string(s.GetCloudProvider()))
return err
}
}
// 批量更新
if len(needUpdateData) > 0 {
err = c.batchUpdateDb(ctx, needUpdateData)
if err != nil {
log.Error("BatchUpdateDb failed "+action, zap.Any("needUpdateSize", len(needUpdateData)), zap.Error(err), utils.ZapTraceIdField(ctx))
cat.LogError(err, string(s.GetCloudProvider()))
return err
}
}
var needDeleteData []T
// 数据库中存在,云上不存在,删除数据库
for _, dbData := range dbDataList {
existsInCloud := false
for _, cloudData := range cloudDataList {
if c.isSameIdentity(cloudData, dbData) {
existsInCloud = true
break
}
}
if !existsInCloud {
needDeleteData = append(needDeleteData, dbData)
}
}
// 批量删除
if len(needDeleteData) > 0 {
for _, dbData := range needDeleteData {
log.Info("need delete "+action, zap.Any("param", dbData), utils.ZapTraceIdField(ctx))
err = c.deleteDb(ctx, dbData)
if err != nil {
log.Error("delete db failed "+action, zap.Any("param", dbData), zap.Error(err), utils.ZapTraceIdField(ctx))
cat.LogError(err, string(s.GetCloudProvider()))
}
}
}
log.Warn(fmt.Sprintf("[%s] finished,cloudProvider:[%s],cost:[%.1f]s.", action, s.GetCloudProvider(), time.Since(start).Seconds()),
zap.Any("result", map[string]any{
"cost": time.Since(start).String(),
"insertSize": len(needInsertData),
"updateSize": len(needUpdateData),
"deleteSize": len(needDeleteData),
"cloudSize": len(cloudDataList),
"dbSize": len(dbDataList),
}), utils.ZapTraceIdField(ctx))
return nil
}
// CollectIAMUsers 采集IAM用户
func CollectIAMUsers(ctx context.Context, s cloud.CloudService) error {
template := CollectIAMDateTemplate[*store.IAMUser]{
listDbData: func(ctx context.Context, s cloud.CloudService) ([]*store.IAMUser, error) {
return store.ListIamUsers(ctx, s.GetCloudProvider(), s.GetAccountUid())
},
listCloudData: func(ctx context.Context, s cloud.CloudService) ([]*store.IAMUser, error) {
return s.ListAllIAMUsers(ctx)
},
isSameIdentity: func(cloudData *store.IAMUser, dbData *store.IAMUser) bool {
return cloudData.UID == dbData.UID
},
needUpdate: func(cloudData *store.IAMUser, dbData *store.IAMUser) bool {
return needUpdateIAMUserDb(cloudData, dbData)
},
batchInsertDb: func(ctx context.Context, data []*store.IAMUser) error {
return store.BatchInsertIamUsers(ctx, data)
},
batchUpdateDb: func(ctx context.Context, data []*store.IAMUser) error {
return store.BatchUpdateIamUsers(ctx, data)
},
deleteDb: func(ctx context.Context, data *store.IAMUser) error {
return store.DeleteIamUser(ctx, data)
},
}
return template.Run(ctx, s, "CollectIAMUsers")
}
Will soon take a look, thanks
可以尝试下最新的版本,现在覆盖率已经稳定了
通过
xgo test -cover -coverpkg ./... -coverprofile cover.out ./...
生成的cover.out文件,通过go tool cover -html=cover.out
可以展示出其中某个文件的覆盖率。通过xgo tool coverage serve cover.out
显示覆盖率为0%。但不是所有go文件都有这个问题