Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ce-ankur opened this issue Jul 26, 2023 · 3 comments

Comments

@ce-ankur
Copy link

ce-ankur commented Jul 26, 2023

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

@kataras
Copy link
Owner

kataras commented Jul 30, 2023

Hello @ce-ankur did you try?

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

@ce-ankur
Copy link
Author

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.

@kataras
Copy link
Owner

kataras commented Sep 25, 2023

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants