// Copyright 2019 getensh.com. All rights reserved. // Use of this source code is governed by getensh.com. package ctrl_v1 import ( "context" "gd_management_gateway/common.in/jsonrpc2" "gd_management_gateway/errors" "gd_management_gateway/params/param_base" "gd_management_gateway/params/param_v1_0" "gd_management_gateway/rpc_apis" "gd_management_gateway/rpc_apis/gd_statistics" "gd_management_gateway/rpc_apis/gd_management" "fmt" "strconv" "strings" "sync" "time" "gd_management_gateway/common.in/cache" "gd_management_gateway/common.in/httper" "gd_management_gateway/common.in/task" "gd_management_gateway/common.in/utils" "github.com/astaxie/beego" "github.com/tealeg/xlsx" "go.uber.org/zap" ) const exportPath = "/export/" var ServerPort = "61002" var ServerIp = "" // Operations about access log api type BaseAccessLogController struct { metadata interface{} // 中继元数据 beego.Controller LogID string } // SetPercentForXlsx 单元格设置百分率 func SetPercentForXlsx(percent string, cell *xlsx.Cell) { s := strings.TrimRight(percent, "%") // 对零单独处理 f, _ := strconv.ParseFloat(s, 64) if f == 0 { cell.SetFloatWithFormat(0.0000, "0.00%") return } // 将百分比转为小数形式 f = f / 100.0000 fstring := strconv.FormatFloat(f, 'f', 4, 64) ffloat, _ := strconv.ParseFloat(fstring, 64) // 设置单元格 cell.SetFloatWithFormat(ffloat, "0.00%") } // @Title 访问日志 // @Description 访问日志 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param state query int false "接口调用返回状态" // @Param code query string false "接口调用返回状态" // @Param request_param query string false "请求参数" // @Param search query string false "关键字" // @Param merchant_id query int64 false "商户id" // @Param api_id query int64 false "基础api id" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Param page_size query int64 false "页大小" // @Param page_number query int64 false "页号" // @Param min query float64 false "最小耗时" // @Param max query float64 false "最大耗时" // @Success 200 {object} params.param_v1_0.LogQueryAccessLogResp "响应信息" // @Failure 500 服务器错误 // @router /access_log [get] func (u *BaseAccessLogController) LogQueryAccessLog() { u.LogID = fmt.Sprintf("LogQueryAccessLog[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryAccessLogReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryAccessLogReq{} mreq.PageNumber = req.PageNumber mreq.PageSize = req.PageSize mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ApiId = req.ApiId mreq.MerchantId = req.MerchantId mreq.State = req.State mreq.Code = req.Code mreq.RequestParam = req.RequestParam mreq.Search = req.Search mreq.Max = req.Max mreq.Min = req.Min reply, err := rpc_apis.Statistics.LogQueryAccessLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryAccessLog"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryAccessLogResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 数据源日志 // @Description 数据源日志 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param state query int false "接口调用返回状态" // @Param search query string false "关键字" // @Param request_param query string false "请求参数" // @Param provider_id query int64 false "三方平台id" // @Param provider_api_id query int64 false "三方api id" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Param page_size query int64 false "页大小" // @Param page_number query int64 false "页号" // @Param min query float64 false "最小耗时" // @Param max query float64 false "最大耗时" // @Param raw_code query string false "原始错误码" // @Success 200 {object} params.param_v1_0.LogQueryThirdpartAccessLogResp "响应信息" // @Failure 500 服务器错误 // @router /thirdpart_access_log [get] func (u *BaseAccessLogController) LogQueryThirdpartAccessLog() { u.LogID = fmt.Sprintf("LogQueryThirdpartAccessLog[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryThirdpartAccessLogReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryThirdpartAccessLogReq{} mreq.EndTimestamp = req.EndTimestamp mreq.StartTimestamp = req.StartTimestamp mreq.PageSize = req.PageSize mreq.PageNumber = req.PageNumber mreq.ProviderApiId = req.ProviderApiId mreq.ProviderId = req.ProviderId mreq.State = req.State mreq.RequestParam = req.RequestParam mreq.Search = req.Search mreq.Max = req.Max mreq.Min = req.Min mreq.RawCode = req.RawCode fmt.Println("raw code:",mreq.RawCode,req.RawCode) reply, err := rpc_apis.Statistics.LogQueryThirdpartAccessLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryThirdpartAccessLog"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryThirdpartAccessLogResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 访问日志统计 // @Description 访问日志统计 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param merchant_id query int64 false "商户id" // @Param api_id query int64 false "基础api id" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Param page_size query int64 false "页大小" // @Param page_number query int64 false "页号" // @Success 200 {object} params.param_v1_0.LogQueryAccessLogCountResp "响应信息" // @Failure 500 服务器错误 // @router /access_log_count [get] func (u *BaseAccessLogController) LogQueryAccessLogCount() { u.LogID = fmt.Sprintf("LogQueryAccessLogCount[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryAccessLogCountReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryAccessLogCountReq{} mreq.PageNumber = req.PageNumber mreq.PageSize = req.PageSize mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ApiId = req.ApiId mreq.MerchantId = req.MerchantId reply, err := rpc_apis.Statistics.LogQueryAccessLogCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryAccessLogCount"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryAccessLogCountResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 数据源查询统计 // @Description 数据源查询统 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param provider_id query int64 false "三方平台id" // @Param provider_api_id query int64 false "三方api id" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Param page_size query int64 false "页大小" // @Param page_number query int64 false "页号" // @Success 200 {object} params.param_v1_0.LogQueryThirdpartAccessLogCountResp "响应信息" // @Failure 500 服务器错误 // @router /thirdpart_accesslog_count [get] func (u *BaseAccessLogController) LogQueryThirdpartAccessLogCount() { u.LogID = fmt.Sprintf("LogQueryThirdpartAccessLogCount[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryThirdpartAccessLogCountReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryThirdpartAccessLogCountReq{} mreq.EndTimestamp = req.EndTimestamp mreq.StartTimestamp = req.StartTimestamp mreq.PageSize = req.PageSize mreq.PageNumber = req.PageNumber mreq.ProviderApiId = req.ProviderApiId mreq.ProviderId = req.ProviderId reply, err := rpc_apis.Statistics.LogQueryThirdpartAccessLogCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryThirdpartAccessLogCount"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryThirdpartAccessLogCountResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 访问日志关联数据源日志 // @Description 访问日志关联数据源日志 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param access_id query int true "访问日志id" // @Param create_time query string true "时间" // @Success 200 {object} params.param_v1_0.LogQueryAccessLogThirdpartLogResp "响应信息" // @Failure 500 服务器错误 // @router /access_log_get_thirdpart_log [get] func (u *BaseAccessLogController) LogQueryAccessLogThirdpartLog() { u.LogID = fmt.Sprintf("LogQueryAccessLogThirdpartLog[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryAccessLogThirdpartLogReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryAccessLogThirdpartLogReq{} mreq.AccessId = req.AccessId if req.CreateTime != "" { timeLayout := "2006-01-02" loc, _ := time.LoadLocation("Local") array := strings.Split(req.CreateTime, " ") t, _ := time.ParseInLocation(timeLayout, array[0], loc) mreq.Timestamp = t.Unix() } reply, err := rpc_apis.Statistics.LogQueryAccessLogThirdpartLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryAccessLogThirdpartLog"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryAccessLogThirdpartLogResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 访问日志用户统计报表 // @Description 访问日志用户统计报表 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param merchant_id query int64 false "商户id" // @Param api_id query int64 false "基础api id" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Param page_size query int64 false "页大小" // @Param page_number query int64 false "页号" // @Success 200 {object} params.param_v1_0.LogQueryUserAccessCountResp "响应信息" // @Failure 500 服务器错误 // @router /user_access_count [get] func (u *BaseAccessLogController) LogQueryUserAccessCount() { u.LogID = fmt.Sprintf("LogQueryUserAccessCount[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryUserAccessCountReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryUserAccessCountReq{} mreq.PageNumber = req.PageNumber mreq.PageSize = req.PageSize mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ApiId = req.ApiId mreq.MerchantId = req.MerchantId reply, err := rpc_apis.Statistics.LogQueryUserAccessCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryUserAccessCount"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryUserAccessCountResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 访问日志接口统计详情 // @Description 访问日志接口统计详情 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param merchant_id query int64 false "商户id" // @Param api_id query int64 false "基础api id" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Success 200 {object} params.param_v1_0.LogQueryInterfaceCountResp "响应信息" // @Failure 500 服务器错误 // @router /access_log_interface_count [get] func (u *BaseAccessLogController) LogQueryInterfaceCount() { u.LogID = fmt.Sprintf("LogQueryInterfaceCount[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryInterfaceCountReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryInterfaceCountReq{} mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ApiId = req.ApiId mreq.MerchantId = req.MerchantId reply, err := rpc_apis.Statistics.LogQueryInterfaceCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryInterfaceCount"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryInterfaceCountResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 数据源接口用量统计 // @Description 数据源接口用量统计 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param provider_api_id query int64 false "数据源api id" // @Param time query int64 false "时间" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Success 200 {object} params.param_v1_0.LogQueryThirdpartAccessCountResp "响应信息" // @Failure 500 服务器错误 // @router /thirdpart_access_count [get] func (u *BaseAccessLogController) LogQueryThirdpartAccessCount() { u.LogID = fmt.Sprintf("LogQueryInterfaceCount[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryThirdpartAccessCountReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryThirdpartAccessCountReq{} mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ProviderApiId = req.ProviderApiId if req.Time > 0 { mreq.Time = time.Unix(req.Time, 0).Format("2006-01-02") } reply, err := rpc_apis.Statistics.LogQueryThirdpartAccessCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryThirdpartAccessCount"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryThirdpartAccessCountResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 数据源接口统计报表 // @Description 数据源接口统计报表 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param provider_api_id query int64 false "数据源api id" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Param page_size query int64 false "页大小" // @Param page_number query int64 false "页号" // @Success 200 {object} params.param_v1_0.LogQueryThirdpartInterfaceCountResp "响应信息" // @Failure 500 服务器错误 // @router /thirdpart_access_interface_count [get] func (u *BaseAccessLogController) LogQueryThirdpartInterfaceCount() { u.LogID = fmt.Sprintf("LogQueryThirdpartInterfaceCount[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryThirdpartInterfaceCountReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryThirdpartInterfaceCountReq{} mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ProviderApiId = req.ProviderApiId mreq.PageNumber = req.PageNumber mreq.PageSize = req.PageSize reply, err := rpc_apis.Statistics.LogQueryThirdpartInterfaceCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryThirdpartInterfaceCount"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryThirdpartInterfaceCountResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } func ExportUpdate(u *BaseAccessLogController, exportReq *gd_statistics.LogExportCreateReq) { _, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), exportReq) if err != nil { l.Error("rpc", zap.String("call", "LogExportCreate"), zap.String("args", utils.MarshalJsonString(exportReq)), zap.String("error", err.Error())) } } var ErrCodeMutex sync.Mutex var ErrorCodeMap = map[string]string{} func IsErrorCodeMapExist() bool { ErrCodeMutex.Lock() defer ErrCodeMutex.Unlock() if len(ErrorCodeMap) > 0 { return true } return false } func SetErrorCodeMap() { ErrCodeMutex.Lock() defer ErrCodeMutex.Unlock() mreq := gd_management.ManagementGetErrorListReq{} mreq.PageNumber = 1 mreq.IsAll = true reply, err := rpc_apis.Management.ManagementGetErrorList(context.Background(), &mreq) if err != nil { return } ErrorCodeMap = map[string]string{} for _, v := range reply.ErrorCodeList { ErrorCodeMap[v.Code] = v.Msg } } func makeXlsxErrorHeader(sheet *xlsx.Sheet, codes []gd_statistics.ErrorCodeCount) { if IsErrorCodeMapExist() == false { SetErrorCodeMap() } row := sheet.AddRow() cell := row.AddCell() cell.Value = "日期" cell = row.AddCell() cell.Value = "错误总量" for _, v := range codes { cell := row.AddCell() if msg, ok := ErrorCodeMap[v.Code]; ok { cell.Value = fmt.Sprintf("%s(%s)", v.Code, msg) } else { cell.Value = v.Code } cell = row.AddCell() cell.Value = v.Code + "占比" } } func makeXlsxSourceHeader(sheet *xlsx.Sheet, names []gd_statistics.SourceNameCount) { row := sheet.AddRow() cell := row.AddCell() cell.Value = "日期" cell = row.AddCell() cell.Value = "来源总量" for _, v := range names { cell := row.AddCell() cell.Value = v.Name cell = row.AddCell() cell.Value = v.Name + "占比" } } func makeXlsxHeader(sheet *xlsx.Sheet, timeList string) { tArray := strings.Split(timeList, ",") row := sheet.AddRow() dateCell := row.AddCell() dateCell.Value = "时间" //dateCell.HMerge dateCell.VMerge = 1 cell := row.AddCell() cell.Value = "总调用量情况" cell.HMerge = 4 row.AddCell() row.AddCell() row.AddCell() row.AddCell() cell = row.AddCell() cell.Value = "有效调用量情况" cell.HMerge = 10 if len(tArray) > 0 && tArray[0] != "" { cell.HMerge += len(tArray) } row = sheet.AddRow() row.AddCell() totalCell := row.AddCell() totalCell.Value = "调用总量" validCell := row.AddCell() validCell.Value = "有效量" validRateCell := row.AddCell() validRateCell.Value = "有效率" chargeCell := row.AddCell() chargeCell.Value = "计费量" chargeRateCell := row.AddCell() chargeRateCell.Value = "计费率" successCell := row.AddCell() successCell.Value = "成功量" successRateCell := row.AddCell() successRateCell.Value = "成功率" queryCell := row.AddCell() queryCell.Value = "查得量" queryRateCell := row.AddCell() queryRateCell.Value = "查得率" reuseCell := row.AddCell() reuseCell.Value = "复用量" reuseRateCell := row.AddCell() reuseRateCell.Value = "复用率" platformErrorCell := row.AddCell() platformErrorCell.Value = "平台异常量" platformErrorRateCell := row.AddCell() platformErrorRateCell.Value = "平台异常率" providerErrorCell := row.AddCell() providerErrorCell.Value = "数据源异常量" providerErrorRateCell := row.AddCell() providerErrorRateCell.Value = "数据源异常率" avgElapsedCell := row.AddCell() avgElapsedCell.Value = "平均时长" offset := 17 for i, v := range tArray { if v == "" { return } cell := row.AddCell() cell.Value = fmt.Sprintf("时长大于%s秒", v) sheet.SetColWidth(17+i, 17+i, 20) offset++ } for i, v := range tArray { if v == "" { return } cell := row.AddCell() cell.Value = fmt.Sprintf("计费调用中时长大于%s秒", v) sheet.SetColWidth(offset+i, offset+i, 30) } } func makeProviderXlsxHeader(sheet *xlsx.Sheet, timeList string) { row := sheet.AddRow() dateCell := row.AddCell() dateCell.Value = "时间" nameCell := row.AddCell() nameCell.Value = "供应商" totalCell := row.AddCell() totalCell.Value = "总量" successCell := row.AddCell() successCell.Value = "成功" failCell := row.AddCell() failCell.Value = "失败" failRateCell := row.AddCell() failRateCell.Value = "失败率" queryCell := row.AddCell() queryCell.Value = "查得" queryNoRecordCell := row.AddCell() queryNoRecordCell.Value = "查无" queryNoRecordRateCell := row.AddCell() queryNoRecordRateCell.Value = "查无率" avgElapsedCell := row.AddCell() avgElapsedCell.Value = "平均时长" tArray := strings.Split(timeList, ",") for _, v := range tArray { if v == "" { break } cell := row.AddCell() cell.Value = fmt.Sprintf("时长大于%s秒", v) } for _, v := range tArray { if v == "" { break } cell := row.AddCell() cell.Value = fmt.Sprintf("计费调用中时长大于%s秒", v) } } func parseSumRate(rate string) string { array := strings.Split(rate, "-") total := float64(0) for _, v := range array { valuestring := strings.TrimRight(v, "%") value, _ := strconv.ParseFloat(valuestring, 64) total += value } ret := strconv.FormatFloat(float64(total)/float64(len(array)), 'f', 3, 64) + "%" return ret } func parseSum(sum *gd_statistics.LogQueryUserAcessCountExport, sheet *xlsx.Sheet) { row := sheet.AddRow() if sum.Total == 0 { sum.ValidRate = "0%" sum.ChargeRate = "0%" } else { sum.ValidRate = strconv.FormatFloat(float64(100*sum.Valid)/float64(sum.Total), 'f', 2, 64) + "%" sum.ChargeRate = strconv.FormatFloat(float64(100*sum.Charge)/float64(sum.Total), 'f', 2, 64) + "%" } if sum.Valid == 0 { sum.QueryRate = "0%" sum.SuccessRate = "0%" sum.ReuseRate = "0%" } else { sum.QueryRate = strconv.FormatFloat(float64(100*sum.Query)/float64(sum.Valid), 'f', 2, 64) + "%" sum.SuccessRate = strconv.FormatFloat(float64(100*sum.Success)/float64(sum.Valid), 'f', 2, 64) + "%" sum.ReuseRate = strconv.FormatFloat(float64(100*sum.Reuse)/float64(sum.Valid), 'f', 2, 64) + "%" sum.PlatformErrorRate = strconv.FormatFloat(float64(100*sum.PlatformError)/float64(sum.Valid), 'f', 2, 64) + "%" sum.ProviderErrorRate = strconv.FormatFloat(float64(100*sum.ProviderError)/float64(sum.Valid), 'f', 2, 64) + "%" } dateCell := row.AddCell() dateCell.Value = sum.Date totalCell := row.AddCell() totalCell.SetInt(int(sum.Total)) validCell := row.AddCell() validCell.SetInt(int(sum.Valid)) validRateCell := row.AddCell() validRateCell.Value = sum.ValidRate SetPercentForXlsx(sum.ValidRate, validRateCell) chargeCell := row.AddCell() chargeCell.SetInt(sum.Charge) chargeRateCell := row.AddCell() SetPercentForXlsx(sum.ChargeRate, chargeRateCell) successCell := row.AddCell() successCell.SetInt(sum.Success) successRateCell := row.AddCell() SetPercentForXlsx(sum.SuccessRate, successRateCell) queryCell := row.AddCell() queryCell.SetInt(sum.Query) queryRateCell := row.AddCell() SetPercentForXlsx(sum.QueryRate, queryRateCell) reuseCell := row.AddCell() reuseCell.SetInt(sum.Reuse) reuseRateCell := row.AddCell() SetPercentForXlsx(sum.ReuseRate, reuseRateCell) platformErrorCell := row.AddCell() platformErrorCell.SetInt(sum.PlatformError) platformErrorRateCell := row.AddCell() SetPercentForXlsx(sum.PlatformErrorRate, platformErrorRateCell) providerErrorCell := row.AddCell() providerErrorCell.SetInt(sum.ProviderError) providerErrorRateCell := row.AddCell() SetPercentForXlsx(sum.ProviderErrorRate, providerErrorRateCell) avgElapsedCell := row.AddCell() sum.AvgElapsed = sum.SumElapsed / float64(sum.Total) elStr := strconv.FormatFloat(sum.AvgElapsed, 'f', 2, 64) el, _ := strconv.ParseFloat(elStr, 64) avgElapsedCell.SetFloatWithFormat(el, "0.00") for _, v := range sum.BigElapsedList { cell := row.AddCell() cell.SetInt(v) } for _, v := range sum.ChargeBigElapsedList { cell := row.AddCell() cell.SetInt(v) } } func parseProviderSum(sum *gd_statistics.LogQueryProviderCountExport, sheet *xlsx.Sheet) { row := sheet.AddRow() if sum.Total == 0 { sum.FailedRate = "0%" sum.QueryNoRecordRate = "0%" } else { sum.FailedRate = strconv.FormatFloat(float64(100*sum.Failed)/float64(sum.Total), 'f', 2, 64) + "%" sum.QueryNoRecordRate = strconv.FormatFloat(float64(100*sum.QueryNoRecord)/float64(sum.Total), 'f', 2, 64) + "%" } dateCell := row.AddCell() dateCell.Value = sum.Date nameCell := row.AddCell() nameCell.Value = " " totalCell := row.AddCell() totalCell.SetInt(int(sum.Total)) successCell := row.AddCell() successCell.SetInt(int(sum.Success)) failedCell := row.AddCell() failedCell.SetInt(int(sum.Failed)) failedRateCell := row.AddCell() SetPercentForXlsx(sum.FailedRate, failedRateCell) queryCell := row.AddCell() queryCell.SetInt(int(sum.Query)) queryNoRecordCell := row.AddCell() queryNoRecordCell.SetInt(int(sum.QueryNoRecord)) queryNoRecordRateCell := row.AddCell() SetPercentForXlsx(sum.QueryNoRecordRate, queryNoRecordRateCell) avgElapsedCell := row.AddCell() elStr := strconv.FormatFloat(sum.SumElapsed/float64(sum.Total), 'f', 2, 64) el, _ := strconv.ParseFloat(elStr, 64) avgElapsedCell.SetFloatWithFormat(el, "0.00") for _, v := range sum.BigElapsedList { cell := row.AddCell() cell.SetInt(v) } for _, v := range sum.ChargeBigElapsedList { cell := row.AddCell() cell.SetInt(v) } } func parseErrorsCount(reply *gd_statistics.LogQueryUserAccessCountExportReply, file *xlsx.File) error { table := make(map[string][]gd_statistics.ErrorExport, 0) for index, _ := range reply.ErrorCount { table[reply.ErrorCount[index].ApiName] = append(table[reply.ErrorCount[index].ApiName], reply.ErrorCount[index]) } if len(table) == 0 { file.AddSheet("空") } for k, v := range table { sheet, err := file.AddSheet(k + "失败分布") if err != nil { return err } makeXlsxErrorHeader(sheet, v[0].Errors) sumTotal := 0 sumRate := make([]gd_statistics.ErrorCodeCount, len(v[0].Errors)) for index, _ := range v { row := sheet.AddRow() cell := row.AddCell() cell.Value = v[index].Date cell = row.AddCell() cell.Value = fmt.Sprintf("%d", v[index].Total) sumTotal += v[index].Total for i := 0; i < len(v[index].Errors); i++ { cell := row.AddCell() cell.Value = fmt.Sprintf("%d", v[index].Errors[i].Count) cell = row.AddCell() cell.Value = v[index].Errors[i].Rate sumRate[i].Count += v[index].Errors[i].Count } } row := sheet.AddRow() cell := row.AddCell() cell.Value = "总" cell = row.AddCell() cell.Value = fmt.Sprintf("%d", sumTotal) for i := 0; i < len(sumRate); i++ { cell = row.AddCell() cell.Value = fmt.Sprintf("%d", sumRate[i].Count) cell = row.AddCell() cell.Value = strconv.FormatFloat(float64(100*sumRate[i].Count)/float64(sumTotal), 'f', 2, 64) + "%" } } return nil } func parseSourceCount(reply *gd_statistics.LogQueryUserAccessCountExportReply, file *xlsx.File) error { table := make(map[string][]gd_statistics.SourceExport, 0) for index, _ := range reply.SourceCount { table[reply.SourceCount[index].ApiName] = append(table[reply.SourceCount[index].ApiName], reply.SourceCount[index]) } if len(table) == 0 { file.AddSheet("空") } for k, v := range table { sheet, err := file.AddSheet(k + "来源分布") if err != nil { return err } makeXlsxSourceHeader(sheet, v[0].Sources) sumTotal := 0 sumRate := make([]gd_statistics.SourceNameCount, len(v[0].Sources)) for index, _ := range v { row := sheet.AddRow() cell := row.AddCell() cell.Value = v[index].Date cell = row.AddCell() cell.Value = fmt.Sprintf("%d", v[index].Total) sumTotal += v[index].Total for i := 0; i < len(v[index].Sources); i++ { cell := row.AddCell() cell.Value = fmt.Sprintf("%d", v[index].Sources[i].Count) cell = row.AddCell() cell.Value = v[index].Sources[i].Rate sumRate[i].Count += v[index].Sources[i].Count } } row := sheet.AddRow() cell := row.AddCell() cell.Value = "总" cell = row.AddCell() cell.Value = fmt.Sprintf("%d", sumTotal) for i := 0; i < len(sumRate); i++ { cell = row.AddCell() cell.Value = fmt.Sprintf("%d", sumRate[i].Count) cell = row.AddCell() cell.Value = strconv.FormatFloat(float64(100*sumRate[i].Count)/float64(sumTotal), 'f', 2, 64) + "%" } } return nil } func sumBigElapseds(oldList []int, newList []int) []int { if len(oldList) == 0 { return newList } if len(oldList) != len(newList) { return oldList } for i, _ := range oldList { oldList[i] = oldList[i] + newList[i] } return oldList } func setAllCells(file *xlsx.File) { style := xlsx.NewStyle() font := xlsx.NewFont(10, "Microsoft YaHei") style.Font = *font style.Border = *xlsx.NewBorder("thin", "none", "thin", "thin") headerStyle := xlsx.NewStyle() fill := xlsx.NewFill("solid", "00B0C4DE", "00000000") headerStyle.Font = *font headerStyle.Fill = *fill headerStyle.Border = *xlsx.NewBorder("thin", "none", "thin", "thin") sheets := file.Sheets for i := 0; i < len(sheets); i++ { rows := sheets[i].Rows for j := 0; j < len(rows); j++ { cells := rows[j].Cells for k := 0; k < len(cells); k++ { if j < 2 { cells[k].SetStyle(headerStyle) } else { cells[k].SetStyle(style) } } } } } func parseAccessCount(reply *gd_statistics.LogQueryUserAccessCountExportReply, file *xlsx.File, timeList string) error { table := make(map[string][]gd_statistics.LogQueryUserAcessCountExport, 0) for index, _ := range reply.LogQueryUserAcessCount { table[reply.LogQueryUserAcessCount[index].ApiName] = append(table[reply.LogQueryUserAcessCount[index].ApiName], reply.LogQueryUserAcessCount[index]) } if len(table) == 0 { file.AddSheet("空") } for k, v := range table { sheet, err := file.AddSheet(k + "指标") if err != nil { return err } makeXlsxHeader(sheet, timeList) sum := gd_statistics.LogQueryUserAcessCountExport{} sum.Date = "总" for index, _ := range v { row := sheet.AddRow() dateCell := row.AddCell() dateCell.Value = v[index].Date totalCell := row.AddCell() sum.Total += int(v[index].Total) totalCell.SetInt(int(v[index].Total)) validCell := row.AddCell() sum.Valid += int(v[index].Valid) validCell.SetInt(int(v[index].Valid)) validRateCell := row.AddCell() SetPercentForXlsx(v[index].ValidRate, validRateCell) chargeCell := row.AddCell() sum.Charge += int(v[index].Charge) chargeCell.SetInt(int(v[index].Charge)) chargeRateCell := row.AddCell() SetPercentForXlsx(v[index].ChargeRate, chargeRateCell) successCell := row.AddCell() successCell.SetInt(v[index].Success) sum.Success += v[index].Success successRateCell := row.AddCell() SetPercentForXlsx(v[index].SuccessRate, successRateCell) queryCell := row.AddCell() queryCell.SetInt(v[index].Query) sum.Query += v[index].Query queryRateCell := row.AddCell() SetPercentForXlsx(v[index].QueryRate, queryRateCell) reuseCell := row.AddCell() reuseCell.SetInt(v[index].Reuse) sum.Reuse += v[index].Reuse reuseRateCell := row.AddCell() SetPercentForXlsx(v[index].ReuseRate, reuseRateCell) platformErrorCell := row.AddCell() platformErrorCell.SetInt(v[index].PlatformError) sum.PlatformError += v[index].PlatformError platformErrorRateCell := row.AddCell() SetPercentForXlsx(v[index].PlatformErrorRate, platformErrorRateCell) providerErrorCell := row.AddCell() providerErrorCell.SetInt(v[index].ProviderError) sum.ProviderError += v[index].ProviderError providerErrorRateCell := row.AddCell() SetPercentForXlsx(v[index].ProviderErrorRate, providerErrorRateCell) avgElapsedCell := row.AddCell() elStr := strconv.FormatFloat(v[index].AvgElapsed, 'f', 2, 64) el, _ := strconv.ParseFloat(elStr, 64) avgElapsedCell.SetFloatWithFormat(el, "0.00") sum.SumElapsed += v[index].SumElapsed for _, big := range v[index].BigElapsedList { cell := row.AddCell() cell.SetInt(big) } sum.BigElapsedList = sumBigElapseds(sum.BigElapsedList, v[index].BigElapsedList) for _, big := range v[index].ChargeBigElapsedList { cell := row.AddCell() cell.SetInt(big) } sum.ChargeBigElapsedList = sumBigElapseds(sum.ChargeBigElapsedList, v[index].ChargeBigElapsedList) } parseSum(&sum, sheet) } return nil } // @Title 访问日志用户统计报表导出 // @Description 访问日志用户统计报表导出 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param export body rpc_apis.gd_statistics.LogQueryUserAccessCountExportReq true "数据源" // @Success 200 {object} params.param_v1_0.LogQueryUserAccessCountResp "响应信息" // @Failure 500 服务器错误 // @router /user_access_count_export [post] func (u *BaseAccessLogController) LogQueryUserAccessCountExport() { u.LogID = fmt.Sprintf("LogQueryUserAccessCountExport[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryUserAccessCountExportReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { exportReq := gd_statistics.LogExportCreateReq{} exportReq.Status = "开始" exportReq.FileName = req.Export.ExportName if exportReq.FileName == "" { return errors.ArgsError } host := u.Ctx.Request.Host if strings.Contains(ServerIp, "0.0.0.0") == false { host = ServerIp + ":" + ServerPort } else if strings.Contains(u.Ctx.Request.Host, ":") == false { host = u.Ctx.Request.Host + ":" + ServerPort } exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx" if true { exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx") } exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq) if err != nil { l.Error("rpc", zap.String("call", "LogExportCreate"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } exportReq.Id = exportReply.Id defer ExportUpdate(u, &exportReq) mreq := gd_statistics.LogQueryUserAccessCountExportReq{} mreq.StartTimestamp = req.Export.StartTimestamp mreq.EndTimestamp = req.Export.EndTimestamp mreq.ApiIdList = req.Export.ApiIdList mreq.MerchantId = req.Export.MerchantId mreq.TimeList = req.Export.TimeList reply, err := rpc_apis.Statistics.LogQueryUserAccessCountExport(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryUserAccessCountExport"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) exportReq.Status = "失败" return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryUserAccessCountExportResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } file := xlsx.NewFile() if err := parseAccessCount(&reply, file, mreq.TimeList); err != nil { exportReq.Status = "失败" return err } if err := parseErrorsCount(&reply, file); err != nil { exportReq.Status = "失败" return err } if err := parseSourceCount(&reply, file); err != nil { exportReq.Status = "失败" return err } setAllCells(file) err = file.Save(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx") if true { utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx") } //resp.Data = reply if err != nil { exportReq.Status = "失败" } else { exportReq.Status = "完成" } httper.JSON(u.Ctx, resp, u.LogID) return err } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 数据源日志用户统计报表导出 // @Description 数据源日志用户统计报表导出 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param export body rpc_apis.gd_statistics.LogQueryProviderCountExportReq true "" // @Success 200 {object} params.param_v1_0.LogQueryProviderCountExportResp "响应信息" // @Failure 500 服务器错误 // @router /provider_count_export [post] func (u *BaseAccessLogController) LogQueryProviderCountExport() { u.LogID = fmt.Sprintf("LogQueryProviderCountExport[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryProviderCountExportReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { exportReq := gd_statistics.LogExportCreateReq{} exportReq.ExportType = 1 exportReq.Status = "开始" exportReq.FileName = req.Export.ExportName if exportReq.FileName == "" { return errors.ArgsError } host := u.Ctx.Request.Host if strings.Contains(ServerIp, "0.0.0.0") == false { host = ServerIp + ":" + ServerPort } else if strings.Contains(u.Ctx.Request.Host, ":") == false { host = u.Ctx.Request.Host + ":" + ServerPort } exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx" if true { exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx") } exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq) if err != nil { l.Error("rpc", zap.String("call", "LogExportCreate"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } exportReq.Id = exportReply.Id defer ExportUpdate(u, &exportReq) mreq := gd_statistics.LogQueryProviderCountExportReq{} mreq.StartTimestamp = req.Export.StartTimestamp mreq.EndTimestamp = req.Export.EndTimestamp mreq.ProviderApiIdList = req.Export.ProviderApiIdList mreq.ProviderId = req.Export.ProviderId mreq.TimeList = req.Export.TimeList reply, err := rpc_apis.Statistics.LogQueryProviderCountExport(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryProviderCountExport"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) exportReq.Status = "失败" return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryProviderCountExportResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } table := make(map[string][]gd_statistics.LogQueryProviderCountExport, 0) for index, _ := range reply.LogQueryProviderCount { table[reply.LogQueryProviderCount[index].ProviderApiName] = append(table[reply.LogQueryProviderCount[index].ProviderApiName], reply.LogQueryProviderCount[index]) } file := xlsx.NewFile() if len(table) == 0 { file.AddSheet("空") } for k, v := range table { sheet, err := file.AddSheet(k) if err != nil { exportReq.Status = "失败" return err } makeProviderXlsxHeader(sheet, mreq.TimeList) sum := gd_statistics.LogQueryProviderCountExport{} sum.Date = "总" for index, _ := range v { row := sheet.AddRow() dateCell := row.AddCell() dateCell.Value = v[index].Date nameCell := row.AddCell() nameCell.Value = v[index].ProviderName totalCell := row.AddCell() sum.Total += v[index].Total totalCell.SetInt(int(v[index].Total)) successCell := row.AddCell() sum.Success += v[index].Success successCell.SetInt(int(v[index].Success)) failedCell := row.AddCell() sum.Failed += v[index].Failed failedCell.SetInt(int(v[index].Failed)) failedRateCell := row.AddCell() SetPercentForXlsx(v[index].FailedRate, failedRateCell) queryCell := row.AddCell() queryCell.SetInt(int(v[index].Query)) sum.Query += v[index].Query queryNoRecordCell := row.AddCell() queryNoRecordCell.SetInt(int(v[index].QueryNoRecord)) sum.QueryNoRecord += v[index].QueryNoRecord queryNoRecordRateCell := row.AddCell() SetPercentForXlsx(v[index].QueryNoRecordRate, queryNoRecordRateCell) avgElapsedCell := row.AddCell() elStr := strconv.FormatFloat(v[index].AvgElapsed, 'f', 2, 64) el, _ := strconv.ParseFloat(elStr, 64) avgElapsedCell.SetFloatWithFormat(el, "0.00") sum.AvgElapsed += v[index].AvgElapsed sum.SumElapsed += v[index].SumElapsed for _, big := range v[index].BigElapsedList { cell := row.AddCell() cell.SetInt(big) } sum.BigElapsedList = sumBigElapseds(sum.BigElapsedList, v[index].BigElapsedList) for _, big := range v[index].ChargeBigElapsedList { cell := row.AddCell() cell.SetInt(big) } sum.ChargeBigElapsedList = sumBigElapseds(sum.ChargeBigElapsedList, v[index].ChargeBigElapsedList) } parseProviderSum(&sum, sheet) } err = file.Save(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx") if true { utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx") } //resp.Data = reply if err != nil { exportReq.Status = "失败" } else { exportReq.Status = "完成" } httper.JSON(u.Ctx, resp, u.LogID) return err } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } var exportStatusMap = map[string]int{ "开始": 1, "完成": 2, "失败": 3, } // 导出文件时去掉文件后的时间戳后缀 func convertExportFileName(src string) string { array := strings.Split(src, "_") length := len(array) if length < 2 { return src } timestampString := array[length-1] if len([]byte(timestampString)) < 19 { return src } _, err := strconv.ParseInt(timestampString, 10, 64) if err != nil { return src } return strings.TrimRight(src, "_"+timestampString) } // @Title 获取导出列表 // @Description 获取导出列表 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param page_number query int64 false "当前页" // @Param is_all query bool false "是否返回所有" // @Param export_type query int false "api报表或数据源列表" // @Success 200 {object} params.param_v1_0.LogExportListResp "响应信息" // @Failure 500 服务器错误 // @router /exports [get] func (u *BaseAccessLogController) LogExportList() { u.LogID = fmt.Sprintf("LogExportList[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogExportListReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogExportListReq{} mreq.PageNumber = req.PageNumber mreq.IsAll = req.IsAll mreq.ExportType = req.ExportType reply, err := rpc_apis.Statistics.LogExportList(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogExportList"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogExportListResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } for i, v := range reply.ExportList { reply.ExportList[i].StatusCode, _ = exportStatusMap[v.Status] reply.ExportList[i].FileName = convertExportFileName(v.FileName) } resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 删除导出报表 // @Description 删除导出报表 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param id query int64 false "导出报告id" // @Success 200 {object} params.param_v1_0.LogExportDeleteResp "响应信息" // @Failure 500 服务器错误 // @router /export [delete] func (u *BaseAccessLogController) LogExportDelete() { u.LogID = fmt.Sprintf("LogExportDelete[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogExportDeleteReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogExportDeleteReq{} mreq.Id = req.Id mreq.ExportDir = beego.BConfig.WebConfig.StaticDir["/export"] reply, err := rpc_apis.Statistics.LogExportDelete(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogExportDelete"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } if reply.RealPath != "" { cache.Redis.Publish(BatchRemoveFileNotifyChannel, reply.RealPath) } resp := param_v1_0.LogExportDeleteResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } //resp.Data = reply httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 访问日志接口异常分析 // @Description 访问日志接口异常分析 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param merchant_id query int64 false "商户id" // @Param api_id query int64 false "基础api id" // @Param start_timestamp query int64 false "开始时间" // @Param status query int false "0 全部 1 成功 2 失败" // @Param end_timestamp query int64 false "结束时间" // @Success 200 {object} params.param_v1_0.LogQueryInterfaceAnalyzeResp "响应信息" // @Failure 500 服务器错误 // @router /access_log_interface_analyze [get] func (u *BaseAccessLogController) LogQueryInterfaceAnalyze() { u.LogID = fmt.Sprintf("LogQueryInterfaceAnalyze[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryInterfaceCountReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryInterfaceCountReq{} mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ApiId = req.ApiId mreq.MerchantId = req.MerchantId mreq.Option = req.Status reply, err := rpc_apis.Statistics.LogQueryInterfaceAnalyzeError(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryInterfaceAnalyzeError"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.LogQueryInterfaceAnalyzeResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, Data: make([]gd_statistics.LogQueryInterfaceAnalyzeError, 0), } resp.Data = reply.List httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 访问日志接口数据源分析 // @Description 访问日志接口数据源分析 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param merchant_id query int64 false "商户id" // @Param api_id query int64 false "基础api id" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Success 200 {object} params.param_v1_0.LogQueryInterfaceAnalyzeResp "响应信息" // @Failure 500 服务器错误 // @router /third_party_analyze [get] func (u *BaseAccessLogController) LogQueryThirdPartyAnalyze() { u.LogID = fmt.Sprintf("LogQueryThirdPartyAnalyze[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryInterfaceCountReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.LogQueryInterfaceCountReq{} mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ApiId = req.ApiId mreq.MerchantId = req.MerchantId reply, err := rpc_apis.Statistics.LogQueryInterfaceThirdPartyCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryInterfaceThirdPartyCount"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.ThirdPartyAnalyzeResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, Data: make([]gd_statistics.LogQueryInterfaceThirdPartyCount, 0), } resp.Data = reply.List httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } // @Title 数据源异常分析 // @Description 数据源异常分析 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param provider_api_id query int64 false "基础api id" // @Param status query int false "0 全部 1 成功 2 异常" // @Param start_timestamp query int64 false "开始时间" // @Param end_timestamp query int64 false "结束时间" // @Success 200 {object} params.param_v1_0.ThirdPartyInterfaceErrorAnalyzeResp "响应信息" // @Failure 500 服务器错误 // @router /third_party_err_analyze [get] func (u *BaseAccessLogController) ThirdPartyInterfaceErrorAnalyze() { u.LogID = fmt.Sprintf("LogQueryThirdPartyAnalyze[%d]", time.Now().UnixNano()) req := ¶m_v1_0.ThirdPartyInterfaceErrorAnalyzeReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleTokenCheck := func() error { uid, _, err := utils.ParseToken(req.Token) if err != nil { return err } if uid != req.Uid { return errors.UserTokenillegality } /*if level == 0 { return errors.AuthNotAllow }*/ return nil } handleDataTask := func() error { mreq := gd_statistics.ThirdPartyInterfaceErrorAnalyzeReq{} mreq.StartTimestamp = req.StartTimestamp mreq.EndTimestamp = req.EndTimestamp mreq.ProviderApiId = req.ProviderApiId mreq.Status = req.Status reply, err := rpc_apis.Statistics.ThirdPartyInterfaceErrorAnalyze(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "ThirdPartyInterfaceErrorAnalyze"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } resp := param_v1_0.ThirdPartyInterfaceErrorAnalyzeResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, Data: make([]gd_statistics.ThirdPartyInterfaceErrorAnalyze, 0), } resp.Data = reply.List httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleTokenCheck, handleDataTask, ) } func ExportImpl(req *param_v1_0.LogQueryUserAccessLogExportReq,u *BaseAccessLogController) error { defer func() { if r := recover(); r != nil { err := fmt.Errorf("%+v", r) fmt.Println("export err:",err) } }() var headMap map[string]string if !req.Export.EnglishHeader { hReq := gd_management.ManagementGetBaseApiByRouterReq{} hReq.MerchantId = int(req.Export.MerchantId) hReq.ApiId = int(req.Export.ApiId) hReply, err := rpc_apis.Management.ManagementGetBaseApiByRouter(utils.NewContextFromBeegoCtx(u.Ctx), &hReq) if err != nil { l.Error("rpc", zap.String("call", "ManagementGetBaseApiByRouter"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) //return errors.ErrorTransform(err) } else { headMap = hReply.Data } fmt.Println("ManagementGetBaseApiByRouter:", hReply, err) } // 创建导出任务 req.Export.ExportName = fmt.Sprintf("%s_%d", req.Export.ExportName, time.Now().UnixNano()) exportReq := gd_statistics.LogExportCreateReq{} exportReq.Status = "开始" exportReq.ExportType = 2 exportReq.FileName = req.Export.ExportName if exportReq.FileName == "" { return errors.ArgsError } host := u.Ctx.Request.Host if strings.Contains(ServerIp, "0.0.0.0") == false { host = ServerIp + ":" + ServerPort } else if strings.Contains(u.Ctx.Request.Host, ":") == false { host = u.Ctx.Request.Host + ":" + ServerPort } exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx" if true { exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx") } exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq) if err != nil { l.Error("rpc", zap.String("call", "LogExportCreate"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } exportReq.Id = exportReply.Id // 任务执行完成后更新任务 defer ExportUpdate(u, &exportReq) // 调微服务获取日志数据 mreq := gd_statistics.LogQueryAccessLogReq{} mreq.StartTimestamp = req.Export.StartTimestamp mreq.EndTimestamp = req.Export.EndTimestamp mreq.ApiId = req.Export.ApiId mreq.MerchantId = req.Export.MerchantId mreq.PageNumber = 0 mreq.PageSize = 10000 mreq.UseId = true // 初始化excel manager mg := initLogExcelManagerNew(req.Export.IsParseParam) exportReq.Status = "进行中" ExportUpdate(u, &exportReq) // 考虑到数据量问题分批获取数据 for { fmt.Println("111111111111111111111111111111111111111111111111111111",mreq.PageNumber) mreq.PageNumber += 1 reply, err := rpc_apis.Statistics.LogExport(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogExport"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) exportReq.Status = "失败" return errors.ErrorTransform(err) } logLen := int64(len(reply.AccessLogs)) if len(reply.AccessLogs) == 0 { break } // 写入execel accessLogWriteToExcelNew(mg, reply.AccessLogs, headMap) if logLen < mreq.PageSize{ break } mreq.LastId = reply.AccessLogs[logLen-1].Id } exportReq.Status = "完成" // 保存execel mg.baseSheet.Flush() if req.Export.IsParseParam{ if mg.reqSheet != nil{ mg.reqSheet.Flush() } if mg.resSheet != nil{ mg.resSheet.Flush() } } mg.file.SaveAs(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx") //mg.file.Save(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx") if true { utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx") } return nil } // @Title 平台日志导出 // @Description 平台日志导出 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param export body params.param_v1_0.LogExportInfo true "导出任务信息" // @Success 200 {object} params.param_v1_0.LogQueryUserAccessCountExportResp "响应信息" // @Failure 500 服务器错误 // @router /access_log_export [post] func (u *BaseAccessLogController) LogQueryUserAccessLogExport() { u.LogID = fmt.Sprintf("LogQueryUserAccessLogExport[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryUserAccessLogExportReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleDataTask := func() error { /*var headMap map[string]string if !req.Export.EnglishHeader { hReq := gd_management.ManagementGetBaseApiByRouterReq{} hReq.MerchantId = int(req.Export.MerchantId) hReq.ApiId = int(req.Export.ApiId) hReply, err := rpc_apis.Management.ManagementGetBaseApiByRouter(utils.NewContextFromBeegoCtx(u.Ctx), &hReq) if err != nil { l.Error("rpc", zap.String("call", "ManagementGetBaseApiByRouter"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) } else { headMap = hReply.Data } fmt.Println("ManagementGetBaseApiByRouter:", hReply, err) } // 创建导出任务 req.Export.ExportName = fmt.Sprintf("%s_%d", req.Export.ExportName, time.Now().UnixNano()) exportReq := gd_statistics.LogExportCreateReq{} exportReq.Status = "开始" exportReq.ExportType = 2 exportReq.FileName = req.Export.ExportName if exportReq.FileName == "" { return errors.ArgsError } host := u.Ctx.Request.Host if strings.Contains(ServerIp, "0.0.0.0") == false { host = ServerIp + ":" + ServerPort } else if strings.Contains(u.Ctx.Request.Host, ":") == false { host = u.Ctx.Request.Host + ":" + ServerPort } exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx" if true { exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx") } exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq) if err != nil { l.Error("rpc", zap.String("call", "LogExportCreate"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } exportReq.Id = exportReply.Id defer ExportUpdate(u, &exportReq) mreq := gd_statistics.LogQueryAccessLogReq{} mreq.StartTimestamp = req.Export.StartTimestamp mreq.EndTimestamp = req.Export.EndTimestamp mreq.ApiId = req.Export.ApiId mreq.MerchantId = req.Export.MerchantId mreq.PageNumber = 0 mreq.PageSize = 1000 // 初始化excel manager mg := initLogExcelManagerNew(req.Export.IsParseParam) total := int64(0) handled := int64(0) // 考虑到数据量问题分批获取数据 for { mreq.PageNumber += 1 reply, err := rpc_apis.Statistics.LogQueryAccessLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryAccessLog"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) exportReq.Status = "失败" return errors.ErrorTransform(err) } // 设置总数 if total == 0 { total = reply.Total } // 写入execel accessLogWriteToExcelNew(mg, reply.AccessLogs, headMap) handled += int64(len(reply.AccessLogs)) // 处理完毕 if handled >= total { break } } exportReq.Status = "完成" // 保存execel mg.baseSheet.Flush() if req.Export.IsParseParam{ if mg.reqSheet != nil{ mg.reqSheet.Flush() } if mg.resSheet != nil{ mg.resSheet.Flush() } } mg.file.SaveAs(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx") if true { utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx") }*/ if req.Export.ExportName == "" { return errors.ArgsError } if req.Export.StartTimestamp == 0 || req.Export.EndTimestamp == 0 { return errors.ArgsError } // TODO 判断是否在一个月内 monthstar := time.Unix(req.Export.StartTimestamp,0).Month() monthEnd := time.Unix(req.Export.EndTimestamp,0).Month() if monthstar != monthEnd{ return jsonrpc2.NewJsonError(20001, "参数错误,不能跨月导出") } go ExportImpl(req,u) resp := param_v1_0.LogQueryUserAccessCountExportResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } httper.JSON(u.Ctx, resp, u.LogID) return nil } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleDataTask, ) } // @Title 数据源日志导出 // @Description 数据源日志导出 // @Param token header string true "token" // @Param uid header int64 true "admin id" // @Param export body params.param_v1_0.ThirdpartLogExportInfo true "导出任务信息" // @Success 200 {object} params.param_v1_0.LogQueryUserAccessCountExportResp "响应信息" // @Failure 500 服务器错误 // @router /thirdpart_log_export [post] func (u *BaseAccessLogController) LogQueryUserThirdpartLogExport() { u.LogID = fmt.Sprintf("LogQueryUserThirdpartLogExport[%d]", time.Now().UnixNano()) req := ¶m_v1_0.LogQueryUserThirdpartLogExportReq{} getParamsTask := func() error { httper.FillRequireParams(u.Ctx, req, u.LogID) return nil } handleDataTask := func() error { // 创建导出任务 req.Export.ExportName = fmt.Sprintf("%s_%d", req.Export.ExportName, time.Now().UnixNano()) exportReq := gd_statistics.LogExportCreateReq{} exportReq.Status = "开始" exportReq.ExportType = 3 exportReq.FileName = req.Export.ExportName if exportReq.FileName == "" { return errors.ArgsError } host := ServerIp + ":" + ServerPort exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx" if true { exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx") } exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq) if err != nil { l.Error("rpc", zap.String("call", "LogExportCreate"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) return errors.ErrorTransform(err) } exportReq.Id = exportReply.Id // 任务执行完成后更新任务 defer ExportUpdate(u, &exportReq) // 调微服务获取日志数据 mreq := gd_statistics.LogQueryThirdpartAccessLogReq{} mreq.StartTimestamp = req.Export.StartTimestamp mreq.EndTimestamp = req.Export.EndTimestamp mreq.ProviderApiId = req.Export.ProviderApiId mreq.ProviderId = req.Export.ProviderId mreq.PageNumber = 0 mreq.PageSize = 1000 // 初始化excel manager mg := initLogExcelManager(req.Export.IsParseParam) total := int64(0) handled := int64(0) // 考虑到数据量问题分批获取数据 for { mreq.PageNumber += 1 reply, err := rpc_apis.Statistics.LogQueryThirdpartAccessLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq) if err != nil { l.Error("rpc", zap.String("call", "LogQueryThirdpartAccessLog"), zap.String("args", utils.MarshalJsonString(req)), zap.String("error", err.Error())) exportReq.Status = "失败" return errors.ErrorTransform(err) } // 设置总数 if total == 0 { total = reply.Total } // 数据写入execel thirdLogWriteToExcel(mg, reply.ThirdpartLogs) handled += int64(len(reply.ThirdpartLogs)) // 处理完毕 if handled >= total { break } } exportReq.Status = "完成" // 保存execel mg.file.Save(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx") if true { utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx") } resp := param_v1_0.LogQueryUserAccessCountExportResp{ SimpleResp: param_base.SimpleResp{ Code: 0, Msg: "SUCCESS", }, } httper.JSON(u.Ctx, resp, u.LogID) return err } // 执行以上定义的任务 task.Do(&task.PanicRecover{ Ctx: u.Ctx, LogID: u.LogID}, u.Ctx, getParamsTask, handleDataTask, ) }