Files
cloudpods/pkg/util/logclient/logclient.go
2019-08-29 02:31:50 +08:00

170 lines
5.4 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logclient
import (
"context"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/stringutils"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/appctx"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
)
type SessionGenerator func(ctx context.Context, token mcclient.TokenCredential, region, apiVersion string) *mcclient.ClientSession
var (
DefaultSessionGenerator = auth.GetSession
)
// golang 不支持 const 的string array, http://t.cn/EzAvbw8
var BLACK_LIST_OBJ_TYPE = []string{"parameter"}
var logclientWorkerMan *appsrv.SWorkerManager
func init() {
logclientWorkerMan = appsrv.NewWorkerManager("LogClientWorkerManager", 1, 50, false)
}
type IObject interface {
GetId() string
GetName() string
Keyword() string
}
type IVirtualObject interface {
IObject
GetOwnerId() mcclient.IIdentityProvider
}
type IModule interface {
Create(session *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error)
}
// save log to db.
func AddSimpleActionLog(model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool) {
addLog(model, action, iNotes, userCred, success, time.Time{}, &modules.Actions)
}
func AddActionLogWithContext(ctx context.Context, model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool) {
addLog(model, action, iNotes, userCred, success, appctx.AppContextStartTime(ctx), &modules.Actions)
}
func AddActionLogWithStartable(task cloudcommon.IStartable, model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool) {
addLog(model, action, iNotes, userCred, success, task.GetStartTime(), &modules.Actions)
}
// add websocket log to notify active browser users
func PostWebsocketNotify(model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool) {
addLog(model, action, iNotes, userCred, success, time.Time{}, &modules.Websockets)
}
func addLog(model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool, startTime time.Time, api IModule) {
if !consts.OpsLogEnabled() {
return
}
if ok, _ := utils.InStringArray(model.Keyword(), BLACK_LIST_OBJ_TYPE); ok {
log.Errorf("不支持的 actionlog 类型")
return
}
if action == ACT_UPDATE {
if iNotes == nil {
return
}
if uds, ok := iNotes.(sqlchemy.UpdateDiffs); ok && len(uds) == 0 {
return
}
}
notes := stringutils.Interface2String(iNotes)
objId := model.GetId()
if len(objId) == 0 {
objId = "-"
}
objName := model.GetName()
if len(objName) == 0 {
objName = "-"
}
logentry := jsonutils.NewDict()
logentry.Add(jsonutils.NewString(objName), "obj_name")
logentry.Add(jsonutils.NewString(model.Keyword()), "obj_type")
logentry.Add(jsonutils.NewString(objId), "obj_id")
logentry.Add(jsonutils.NewString(action), "action")
logentry.Add(jsonutils.NewString(userCred.GetUserId()), "user_id")
logentry.Add(jsonutils.NewString(userCred.GetUserName()), "user")
logentry.Add(jsonutils.NewString(userCred.GetTenantId()), "tenant_id")
logentry.Add(jsonutils.NewString(userCred.GetTenantName()), "tenant")
logentry.Add(jsonutils.NewString(userCred.GetDomainId()), "domain_id")
logentry.Add(jsonutils.NewString(userCred.GetDomainName()), "domain")
logentry.Add(jsonutils.NewString(userCred.GetProjectDomainId()), "project_domain_id")
logentry.Add(jsonutils.NewString(userCred.GetProjectDomain()), "project_domain")
logentry.Add(jsonutils.NewString(strings.Join(userCred.GetRoles(), ",")), "roles")
service := consts.GetServiceType()
if len(service) > 0 {
logentry.Add(jsonutils.NewString(service), "service")
}
if !startTime.IsZero() {
logentry.Add(jsonutils.NewString(timeutils.FullIsoTime(startTime)), "start_time")
}
if virtualModel, ok := model.(IVirtualObject); ok {
ownerId := virtualModel.GetOwnerId()
if ownerId != nil {
projectId := ownerId.GetProjectId()
if len(projectId) > 0 {
logentry.Add(jsonutils.NewString(projectId), "owner_tenant_id")
}
domainId := ownerId.GetProjectDomainId()
if len(domainId) > 0 {
logentry.Add(jsonutils.NewString(domainId), "owner_domain_id")
}
}
}
if !success {
// 失败日志
logentry.Add(jsonutils.JSONFalse, "success")
} else {
// 成功日志
logentry.Add(jsonutils.JSONTrue, "success")
}
logentry.Add(jsonutils.NewString(notes), "notes")
logclientWorkerMan.Run(func() {
s := DefaultSessionGenerator(context.Background(), userCred, "", "")
_, err := api.Create(s, logentry)
if err != nil {
log.Errorf("create action log failed %s", err)
}
}, nil, nil)
}