iris icon indicating copy to clipboard operation
iris copied to clipboard

Question about Iris Logging: How to access a logger in other parts of application

Open ce-ankur opened this issue 2 years ago • 3 comments

Env Details:

Iris Version: 12.2.0
go version go1.19.4 darwin/arm64

I am trying to setup my new Iris application as follows:

// main.go
package main

import (
	"myapp/bootstrap"
	"github.com/kataras/iris/v12"
)

func main() {
	bootstrap.InitIrisApp()
	app := bootstrap.GetIrisApp()
	app.Listen(util.GetPortNumber(), iris.WithLowercaseRouting)
}

The bootstrap.go looks like below:

package bootstrap

import (
	"myapp/handler"
	"myapp/structs"
	"myapp/util"
	"strings"
	"time"

	prometheusMiddleware "github.com/iris-contrib/middleware/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"

	"github.com/kataras/golog"
	"github.com/kataras/iris/v12"
)

var irisServer *iris.Application

func getRequestLogger(ctx iris.Context) {

	// write log format as below format
	// $remote_addr $http_method $http_uri $http_user_agent
	ctx.Request().UserAgent()
	ctx.Request().Referer()
	template := "Remote Addr: %s | Path: %s %s | UA: %s "
	ctx.Application().Logger().Infof(template, ctx.RemoteAddr(), ctx.Method(), ctx.Path(), ctx.Request().UserAgent())

	ctx.Next()
}

func InitIrisApp() {

	// initialize default app with default middlewares
	irisServer = iris.Default()

	// configure logger
	initLogger()

	// configure health check
	initHealthCheck()

	// configure prometheus metrics and end points
	initPrometheusMetrics()

	// initRoutes
	initRoutes()

	// configure the env configuration

	// configure error handlers
	irisServer.OnErrorCode(iris.StatusInternalServerError, internalServerErrorHandler)

	// configure graceful shutdown

}

func initHealthCheck() {
	hcAPI := irisServer.Party(util.GetContextPath() + "/health")
	{
		hcAPI.Get("/status", func(ctx iris.Context) {
			ctx.JSON(handler.HealthHandlerIris())
		})
	}
}

func initRoutes() {
	jobsAPI := irisServer.Party(util.GetContextPath() + "/jobs")
	{
		// bind more routes
	}
}

func internalServerErrorHandler(ctx iris.Context) {

	msg := strings.Split(ctx.GetErr().Error(), "\n")

	ctx.JSON(structs.ServerErrorResponse{
		StatusCode:  500,
		Message:     "Unable to process the request. Internal Server error!",
		Description: msg[0],
		Path:        ctx.Path(),
		Timestamp:   time.Now(),
		ApiVersion:  util.GetAPIVersion(),
	})
}

func initPrometheusMetrics() {

	// adding middleware for prometheus
	m := prometheusMiddleware.New("serviceName", 0.3, 1.2, 5.0)
	irisServer.Use(m.ServeHTTP)

	// adding a route for getting prometheus metrics
	irisServer.Get("/prometrics", iris.FromStd(promhttp.Handler()))
}

func initLogger() {
	irisServer.Logger().SetLevel(util.GetRunLogLevel())
	// adding a middleware for logging requests
	irisServer.Use(getRequestLogger)
}

func GetLoggerInstance() *golog.Logger {
	return irisServer.Logger()
}

func GetIrisApp() *iris.Application {
	return irisServer
}

I want to understand once I have setup the logger I want to use it in other parts of the code, like Handlers, service layers, models etc. For this reason I exported a function GetLoggerInstance() in hope that I can use same logger instance in whole code. But I land up in cyclic dependency. Moreover, when I am to use logging methods the correct context of the log must be picked up.

[19:01:49 IST 2023/07/26] [DEFAULT] [INFO] (myapp/util/config:8) Setting project directory as.....
[INFO] 2023/07/26 19:13 Remote Addr: ::1 | Path: GET /api/health/status | UA: PostmanRuntime/7.32.0 

I understand the access logs and different from application logs, but how can I achieve the parity between both of them using iris logger. Unfortunately I was not able to understand this from Docs. Any help is much appreciated. @kataras

ce-ankur avatar Jul 26 '23 13:07 ce-ankur

Hello @ce-ankur did you try?

func myHandler(ctx iris.Context) {
    logger := ctx.Application().Logger()
    // work with "logger" instance...
}

kataras avatar Jul 30 '23 17:07 kataras

HI @kataras This is the easiest approach and I am already using this in my handlers/where-ever the ctx object is available. I question was regarding how can I get logger instance where I don't have context object. I don't think passing either logger or ctx instance is a good idea.

ce-ankur avatar Jul 31 '23 04:07 ce-ankur

@ce-ankur If you use the default Iris logger you can get the logger instance through golog.Default/golog.Debug/Info... so you don't have dependency cycle.

kataras avatar Sep 25 '23 16:09 kataras