| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- // 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"
- "fmt"
- "strings"
- "time"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/appctx"
- "yunion.io/x/pkg/util/stringutils"
- "yunion.io/x/pkg/util/timeutils"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/sqlchemy"
- api "yunion.io/x/onecloud/pkg/apis/logger"
- "yunion.io/x/onecloud/pkg/appsrv"
- "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/logger"
- "yunion.io/x/onecloud/pkg/util/ctx"
- // "yunion.io/x/onecloud/pkg/mcclient/modules/websocket"
- )
- 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 sSimpleObject struct {
- id string
- name string
- keyword string
- }
- func (s sSimpleObject) GetId() string {
- return s.id
- }
- func (s sSimpleObject) GetName() string {
- return s.name
- }
- func (s sSimpleObject) Keyword() string {
- return s.keyword
- }
- func NewSimpleObject(id, name, keyword string) IObject {
- return sSimpleObject{
- id: id,
- name: name,
- keyword: keyword,
- }
- }
- type IVirtualObject interface {
- IObject
- GetOwnerId() mcclient.IIdentityProvider
- }
- type IModule interface {
- Create(session *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error)
- }
- type IStartable interface {
- GetStartTime() time.Time
- }
- // 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{}, &logger.Actions, "", "")
- }
- func AddSimpleActionLog2(model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool, severity api.TEventSeverity, kind api.TEventKind) {
- addLog(model, action, iNotes, userCred, success, time.Time{}, &logger.Actions, severity, kind)
- }
- 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), &logger.Actions, "", "")
- }
- func AddActionLogWithContext2(ctx context.Context, model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool, severity api.TEventSeverity, kind api.TEventKind) {
- addLog(model, action, iNotes, userCred, success, appctx.AppContextStartTime(ctx), &logger.Actions, severity, kind)
- }
- func AddActionLogWithStartable(task IStartable, model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool) {
- addLog(model, action, iNotes, userCred, success, task.GetStartTime(), &logger.Actions, "", "")
- }
- func AddActionLogWithStartable2(task IStartable, model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool, severity api.TEventSeverity, kind api.TEventKind) {
- addLog(model, action, iNotes, userCred, success, task.GetStartTime(), &logger.Actions, severity, kind)
- }
- // 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{}, &websocket.Websockets)
- // }
- func addLog(model IObject, action string, iNotes interface{}, userCred mcclient.TokenCredential, success bool, startTime time.Time, module IModule, severity api.TEventSeverity, kind api.TEventKind) {
- // avoid log loop
- if !consts.OpsLogEnabled() && utils.IsInStringArray(action, []string{
- ACT_CREATE,
- }) {
- 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")
- logentry.Add(jsonutils.NewString(userCred.GetLoginIp()), "ip")
- logentry.Add(jsonutils.NewBool(userCred.IsSystemAccount()), "is_system_account")
- 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")
- if len(severity) == 0 {
- logentry.Add(jsonutils.NewString(string(api.SeverityError)), "severity")
- }
- } else {
- // 成功日志
- logentry.Add(jsonutils.JSONTrue, "success")
- if len(severity) == 0 {
- logentry.Add(jsonutils.NewString(string(api.SeverityInfo)), "severity")
- }
- }
- if len(severity) > 0 {
- logentry.Add(jsonutils.NewString(string(severity)), "severity")
- }
- if len(kind) > 0 {
- logentry.Add(jsonutils.NewString(string(kind)), "kind")
- }
- logentry.Add(jsonutils.NewString(notes), "notes")
- task := &logTask{
- userCred: userCred,
- api: module,
- logentry: logentry,
- }
- // keystone no need to auth
- // if auth.IsAuthed() {
- // task.userCred = auth.AdminCredential()
- // }
- logclientWorkerMan.Run(task, nil, nil)
- }
- type logTask struct {
- userCred mcclient.TokenCredential
- api IModule
- logentry *jsonutils.JSONDict
- }
- func (t *logTask) Run() {
- ctx := ctx.CtxWithTime()
- ctx = context.WithValue(ctx, appctx.APP_CONTEXT_KEY_APPNAME, consts.GetServiceType())
- s := DefaultSessionGenerator(ctx, t.userCred, "")
- _, err := t.api.Create(s, t.logentry)
- if err != nil {
- log.Errorf("create action log %s failed %s", t.logentry, err)
- }
- }
- func (t *logTask) Dump() string {
- return fmt.Sprintf("logTask %v %s", t.api, t.logentry)
- }
|