diff --git a/_examples/logging/request-logger/accesslog/access.log.sample b/_examples/logging/request-logger/accesslog/access.log.sample index ae988beb..09a660b1 100644 --- a/_examples/logging/request-logger/accesslog/access.log.sample +++ b/_examples/logging/request-logger/accesslog/access.log.sample @@ -7,4 +7,4 @@ 2020-09-13 13:38:18 0s 401 GET /admin ::1 0 B 0 B 2020-09-13 13:38:19 0s 200 GET /admin ::1 auth=admin:admin 0 B 48 B 2020-09-13 13:38:22 0s 200 GET /session ::1 session_id=23fe763f-c9d5-4d65-9e1a-2cc8d23d1aa3 session_test_key=session_test_value auth=admin:admin 0 B 2 B -2020-09-13 13:38:25 2.0001204s 200 GET /fields ::1 job_latency=2s auth=admin:admin 0 B 2 B +2020-09-13 13:38:25 2.0001204s 200 GET /fields ::1 job_latency=2s auth=admin:admin user=user-id:user-name 0 B 2 B diff --git a/_examples/logging/request-logger/accesslog/main.go b/_examples/logging/request-logger/accesslog/main.go index 2666509d..8758b36d 100644 --- a/_examples/logging/request-logger/accesslog/main.go +++ b/_examples/logging/request-logger/accesslog/main.go @@ -159,6 +159,16 @@ func sessionHandler(ctx iris.Context) { ctx.WriteString("OK") } +type user struct { + ID string + Username string +} + +// Log custom structs, they can implement the fmt.Stringer interface too. +func (u user) String() string { + return u.ID + ":" + u.Username +} + func fieldsHandler(ctx iris.Context) { start := time.Now() // simulate a heavy job... @@ -169,5 +179,13 @@ func fieldsHandler(ctx iris.Context) { logFields := accesslog.GetFields(ctx) logFields.Set("job_latency", end.Round(time.Second)) + // Simulate a database fetch or anything + // to get a "user" and log it: + u := user{ + ID: "user-id", + Username: "user-name", + } + logFields.Set("user", u) + ctx.WriteString("OK") } diff --git a/_examples/mvc/basic/main.go b/_examples/mvc/basic/main.go index e7f14c1e..f8ca0d6d 100644 --- a/_examples/mvc/basic/main.go +++ b/_examples/mvc/basic/main.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" "github.com/kataras/iris/v12/middleware/recover" "github.com/kataras/iris/v12/sessions" @@ -12,24 +13,32 @@ import ( func main() { app := iris.New() - app.Use(recover.New()) app.Logger().SetLevel("debug") - // Disable verbose logging of routes for this and its children parties - // when the log level is "debug": app.SetRoutesNoLog(true) - mvc.Configure(app.Party("/basic"), basicMVC) + + basic := app.Party("/basic") + { + // Register middlewares to run under the /basic path prefix. + ac := accesslog.File("./basic_access.log") + defer ac.Close() + + basic.UseRouter(ac.Handler) + basic.UseRouter(recover.New()) + + mvc.Configure(basic, basicMVC) + } app.Listen(":8080") } func basicMVC(app *mvc.Application) { // Disable verbose logging of controllers for this and its children mvc apps - // when the log level is "debug": app.SetControllersNoLog(true) + // when the log level is "debug": + app.SetControllersNoLog(true) - // You can use normal middlewares at MVC apps of course. - app.Router.Use(func(ctx iris.Context) { - ctx.Application().Logger().Infof("Path: %s", ctx.Path()) - ctx.Next() - }) + // You can still register middlewares at MVC apps of course. + // The app.Router returns the Party that this MVC + // was registered on. + // app.Router.UseRouter/Use/.... // Register dependencies which will be binding to the controller(s), // can be either a function which accepts an iris.Context and returns a single value (dynamic binding) @@ -37,6 +46,7 @@ func basicMVC(app *mvc.Application) { app.Register( sessions.New(sessions.Config{}).Start, &prefixedLogger{prefix: "DEV"}, + accesslog.GetFields, // Set custom fields through a controller or controller's methods. ) // GET: http://localhost:8080/basic @@ -73,9 +83,9 @@ func (s *prefixedLogger) Log(msg string) { } type basicController struct { - Logger LoggerService - - Session *sessions.Session + Logger LoggerService // the static logger service attached to this app. + Session *sessions.Session // current HTTP session. + LogFields *accesslog.Fields // accesslog middleware custom fields. } func (c *basicController) BeforeActivation(b mvc.BeforeActivation) { @@ -90,6 +100,7 @@ func (c *basicController) AfterActivation(a mvc.AfterActivation) { func (c *basicController) Get() string { count := c.Session.Increment("count", 1) + c.LogFields.Set("count", count) body := fmt.Sprintf("Hello from basicController\nTotal visits from you: %d", count) c.Logger.Log(body) diff --git a/middleware/accesslog/accesslog.go b/middleware/accesslog/accesslog.go index 33dd3eef..4ddde808 100644 --- a/middleware/accesslog/accesslog.go +++ b/middleware/accesslog/accesslog.go @@ -31,6 +31,9 @@ const ( // GetFields returns the accesslog fields for this request. // Returns a store which the caller can use to // set/get/remove custom log fields. Use its `Set` method. +// +// To use with MVC: Register(accesslog.GetFields). +// DI Handlers: ConfigureContainer().RegisterDependency(accesslog.GetFields). func GetFields(ctx *context.Context) (fields *Fields) { if v := ctx.Values().Get(fieldsContextKey); v != nil { fields = v.(*Fields) @@ -60,7 +63,6 @@ func shouldSkip(ctx *context.Context) bool { } type ( - // Fields is a type alias for memstore.Store, used to set // more than one field at serve-time. Same as FieldExtractor. Fields = memstore.Store