From b78418daa5d73249f7d9b461c3e502806a7d16d9 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 26 Mar 2020 12:31:08 +0000 Subject: [PATCH] Support session id (#1632) small nit Support session id Reviewed-on: https://gitea.com/xorm/xorm/pulls/1632 --- core/db.go | 2 +- engine.go | 7 +++++++ log/logger_context.go | 28 ++++++++++++++++++++++++++-- session.go | 30 +++++++++++++++++++++++++----- xorm.go | 1 + 5 files changed, 60 insertions(+), 8 deletions(-) diff --git a/core/db.go b/core/db.go index 6845565d..671d1dc2 100644 --- a/core/db.go +++ b/core/db.go @@ -118,7 +118,7 @@ func (db *DB) NeedLogSQL(ctx context.Context) bool { return false } - v := ctx.Value("__xorm_show_sql") + v := ctx.Value(log.SessionShowSQLKey) if showSQL, ok := v.(bool); ok { return showSQL } diff --git a/engine.go b/engine.go index 49124309..80baaa4f 100644 --- a/engine.go +++ b/engine.go @@ -42,6 +42,13 @@ type Engine struct { TZLocation *time.Location // The timezone of the application DatabaseTZ *time.Location // The timezone of the database + + logSessionID bool // create session id +} + +// EnableSessionID if enable session id +func (engine *Engine) EnableSessionID(enable bool) { + engine.logSessionID = enable } // SetCacher sets cacher for the table diff --git a/log/logger_context.go b/log/logger_context.go index f80091f3..c2d94dc6 100644 --- a/log/logger_context.go +++ b/log/logger_context.go @@ -6,6 +6,7 @@ package log import ( "context" + "fmt" "time" ) @@ -18,6 +19,7 @@ type LogContext struct { Err error // SQL executed error } +// SQLLogger represents an interface to log SQL type SQLLogger interface { BeforeSQL(context LogContext) // only invoked when IsShowSQL is true AfterSQL(context LogContext) // only invoked when IsShowSQL is true @@ -43,55 +45,77 @@ var ( _ ContextLogger = &LoggerAdapter{} ) +// enumerate all the context keys +var ( + SessionIDKey = "__xorm_session_id" + SessionShowSQLKey = "__xorm_show_sql" +) + // LoggerAdapter wraps a Logger interafce as LoggerContext interface type LoggerAdapter struct { logger Logger } +// NewLoggerAdapter creates an adapter for old xorm logger interface func NewLoggerAdapter(logger Logger) ContextLogger { return &LoggerAdapter{ logger: logger, } } +// BeforeSQL implements ContextLogger func (l *LoggerAdapter) BeforeSQL(ctx LogContext) {} +// AfterSQL implements ContextLogger func (l *LoggerAdapter) AfterSQL(ctx LogContext) { + var sessionPart string + v := ctx.Ctx.Value(SessionIDKey) + if key, ok := v.(string); ok { + sessionPart = fmt.Sprintf(" [%s]", key) + } if ctx.ExecuteTime > 0 { - l.logger.Infof("[SQL] %v %v - %v", ctx.SQL, ctx.Args, ctx.ExecuteTime) + l.logger.Infof("[SQL]%s %s %v - %v", sessionPart, ctx.SQL, ctx.Args, ctx.ExecuteTime) } else { - l.logger.Infof("[SQL] %v %v", ctx.SQL, ctx.Args) + l.logger.Infof("[SQL]%s %s %v", sessionPart, ctx.SQL, ctx.Args) } } +// Debugf implements ContextLogger func (l *LoggerAdapter) Debugf(format string, v ...interface{}) { l.logger.Debugf(format, v...) } +// Errorf implements ContextLogger func (l *LoggerAdapter) Errorf(format string, v ...interface{}) { l.logger.Errorf(format, v...) } +// Infof implements ContextLogger func (l *LoggerAdapter) Infof(format string, v ...interface{}) { l.logger.Infof(format, v...) } +// Warnf implements ContextLogger func (l *LoggerAdapter) Warnf(format string, v ...interface{}) { l.logger.Warnf(format, v...) } +// Level implements ContextLogger func (l *LoggerAdapter) Level() LogLevel { return l.logger.Level() } +// SetLevel implements ContextLogger func (l *LoggerAdapter) SetLevel(lv LogLevel) { l.logger.SetLevel(lv) } +// ShowSQL implements ContextLogger func (l *LoggerAdapter) ShowSQL(show ...bool) { l.logger.ShowSQL(show...) } +// IsShowSQL implements ContextLogger func (l *LoggerAdapter) IsShowSQL() bool { return l.logger.IsShowSQL() } diff --git a/session.go b/session.go index 6b8bfbaf..13ebfe27 100644 --- a/session.go +++ b/session.go @@ -6,10 +6,14 @@ package xorm import ( "context" + "crypto/rand" + "crypto/sha256" "database/sql" + "encoding/hex" "errors" "fmt" "hash/crc32" + "io" "reflect" "strings" "time" @@ -19,6 +23,7 @@ import ( "xorm.io/xorm/core" "xorm.io/xorm/internal/json" "xorm.io/xorm/internal/statements" + "xorm.io/xorm/log" "xorm.io/xorm/schemas" ) @@ -92,6 +97,17 @@ func (session *Session) Clone() *Session { return &sess } +func newSessionID() string { + hash := sha256.New() + _, err := io.CopyN(hash, rand.Reader, 50) + if err != nil { + return "????????????????????" + } + md := hash.Sum(nil) + mdStr := hex.EncodeToString(md) + return mdStr[0:20] +} + // Init reset the session as the init status. func (session *Session) Init() { session.statement = statements.NewStatement( @@ -119,7 +135,11 @@ func (session *Session) Init() { session.lastSQL = "" session.lastSQLArgs = []interface{}{} - session.ctx = session.engine.defaultContext + if session.engine.logSessionID { + session.ctx = context.WithValue(session.engine.defaultContext, log.SessionIDKey, newSessionID()) + } else { + session.ctx = session.engine.defaultContext + } } // Close release the connection from pool @@ -264,12 +284,12 @@ func (session *Session) Cascade(trueOrFalse ...bool) *Session { } // MustLogSQL means record SQL or not and don't follow engine's setting -func (session *Session) MustLogSQL(log ...bool) *Session { +func (session *Session) MustLogSQL(logs ...bool) *Session { var showSQL = true - if len(log) > 0 { - showSQL = log[0] + if len(logs) > 0 { + showSQL = logs[0] } - session.ctx = context.WithValue(session.ctx, "__xorm_show_sql", showSQL) + session.ctx = context.WithValue(session.ctx, log.SessionShowSQLKey, showSQL) return session } diff --git a/xorm.go b/xorm.go index e9cd7415..2fe32e50 100644 --- a/xorm.go +++ b/xorm.go @@ -51,6 +51,7 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { driverName: driverName, dataSourceName: dataSourceName, db: db, + logSessionID: false, } if dialect.URI().DBType == schemas.SQLITE {