diff --git a/_examples/mvc/grpc-compatible/main.go b/_examples/mvc/grpc-compatible/main.go index de9af996..f93bf7a1 100644 --- a/_examples/mvc/grpc-compatible/main.go +++ b/_examples/mvc/grpc-compatible/main.go @@ -61,6 +61,14 @@ type myController struct { } // SayHello implements helloworld.GreeterServer. +// See https://github.com/kataras/iris/issues/1449#issuecomment-625570442 +// for the comments below (https://github.com/iris-contrib/swagger). +// +// @Description greet service +// @Accept json +// @Produce json +// @Success 200 {string} string "Hello {name}" +// @Router /helloworld.Greeter/SayHello [post] func (c *myController) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil } diff --git a/configuration.go b/configuration.go index 44bf27a7..9eac65a3 100644 --- a/configuration.go +++ b/configuration.go @@ -185,6 +185,13 @@ var WithGlobalConfiguration = func(app *Application) { app.Configure(WithConfiguration(YAML(globalConfigurationKeyword))) } +// WithLogLevel sets the `Configuration.LogLevel` field. +func WithLogLevel(level string) Configurator { + return func(app *Application) { + app.config.LogLevel = level + } +} + // WithoutServerError will cause to ignore the matched "errors" // from the main application's `Run/Listen` function. // @@ -717,10 +724,24 @@ func (tc TunnelingConfiguration) createTunnel(tunnelAPIRequest ngrokTunnel, publ // these can be passed via options also, look at the top of this file(configuration.go). // Configuration is a valid OptionSetter. type Configuration struct { - // vhost is private and set only with .Run method, it cannot be changed after the first set. + // vhost is private and set only with .Run/Listen methods, it cannot be changed after the first set. // It can be retrieved by the context if needed (i.e router for subdomains) vhost string + // LogLevel is the log level the application should use to output messages. + // Logger, by default, is mostly used on Build state but it is also possible + // that debug error messages could be thrown when the app is running, e.g. + // when malformed data structures try to be sent on Client (i.e Context.JSON/JSONP/XML...). + // + // Defaults to "info". Possible values are: + // * "disable" + // * "fatal" + // * "error" + // * "warn" + // * "info" + // * "debug" + LogLevel string `json:"logLevel" yaml:"LogLevel" toml:"LogLevel" env:"LOG_LEVEL"` + // Tunneling can be optionally set to enable ngrok http(s) tunneling for this Iris app instance. // See the `WithTunneling` Configurator too. Tunneling TunnelingConfiguration `json:"tunneling,omitempty" yaml:"Tunneling" toml:"Tunneling"` @@ -924,6 +945,12 @@ func (c Configuration) GetVHost() string { return c.vhost } +// GetLogLevel returns the `Configuration.LogLevel` field. +// The same (as `golog.LogLevel`) can be retrieved through `app.Logger().Level`. +func (c Configuration) GetLogLevel() string { + return c.vhost +} + // GetDisablePathCorrection returns the Configuration#DisablePathCorrection. // DisablePathCorrection disables the correcting // and redirecting or executing directly the handler of @@ -1094,6 +1121,10 @@ func WithConfiguration(c Configuration) Configurator { return func(app *Application) { main := app.config + if v := c.LogLevel; v != "" { + main.LogLevel = v + } + if c.Tunneling.isEnabled() { main.Tunneling = c.Tunneling } @@ -1201,6 +1232,7 @@ func WithConfiguration(c Configuration) Configurator { // DefaultConfiguration returns the default configuration for an iris station, fills the main Configuration func DefaultConfiguration() Configuration { return Configuration{ + LogLevel: "info", DisableStartupLog: false, DisableInterruptHandler: false, DisablePathCorrection: false, diff --git a/context/configuration.go b/context/configuration.go index e9735180..cdf310ef 100644 --- a/context/configuration.go +++ b/context/configuration.go @@ -1,8 +1,6 @@ package context -import ( - "github.com/kataras/iris/v12/core/netutil" -) +import "github.com/kataras/iris/v12/core/netutil" // ConfigurationReadOnly can be implemented // by Configuration, it's being used inside the Context. @@ -17,6 +15,10 @@ type ConfigurationReadOnly interface { // If original addr was 0.0.0.0, it will return localhost. GetVHost() string + // GetLogLevel returns the `Configuration.LogLevel` field. + // The same (as `golog.LogLevel`) can be retrieved through `app.Logger().Level`. + GetLogLevel() string + // GetDisablePathCorrection returns the configuration.DisablePathCorrection, // DisablePathCorrection corrects and redirects the requested path to the registered path // for example, if /home/ path is requested but no handler for this Route found, diff --git a/core/router/router.go b/core/router/router.go index 2cce0b01..e6ddf8b4 100644 --- a/core/router/router.go +++ b/core/router/router.go @@ -50,12 +50,14 @@ var ErrNotRouteAdder = errors.New("request handler does not implement AddRoute m // Works before or after Build state. // Mainly used for internal cases like `iris.WithSitemap`. // Do NOT use it on serve-time. -func (router *Router) AddRouteUnsafe(r *Route) error { +func (router *Router) AddRouteUnsafe(routes ...*Route) error { if h := router.requestHandler; h != nil { if v, ok := h.(interface { AddRoute(*Route) error }); ok { - return v.AddRoute(r) + for _, r := range routes { + return v.AddRoute(r) + } } } diff --git a/httptest/httptest.go b/httptest/httptest.go index a7bd3f4a..479e3fa7 100644 --- a/httptest/httptest.go +++ b/httptest/httptest.go @@ -89,7 +89,7 @@ func New(t *testing.T, app *iris.Application, setters ...OptionSetter) *httpexpe app.Logger().SetLevel(conf.LogLevel) if err := app.Build(); err != nil { - if conf.LogLevel != "disable" && conf.LogLevel != "disabled" { + if conf.LogLevel != "disable" { app.Logger().Println(err.Error()) return nil } diff --git a/iris.go b/iris.go index 3c1823f6..2b8f7abd 100644 --- a/iris.go +++ b/iris.go @@ -1,7 +1,6 @@ package iris import ( - // std packages "bytes" stdContext "context" "errors" @@ -16,27 +15,18 @@ import ( "sync" "time" - // context for the handlers + "github.com/kataras/iris/v12/cache" "github.com/kataras/iris/v12/context" - "github.com/kataras/iris/v12/hero" - - // core packages, required to build the application "github.com/kataras/iris/v12/core/errgroup" + "github.com/kataras/iris/v12/core/handlerconv" "github.com/kataras/iris/v12/core/host" "github.com/kataras/iris/v12/core/netutil" "github.com/kataras/iris/v12/core/router" - - // handlerconv conversions - "github.com/kataras/iris/v12/core/handlerconv" - // cache conversions - "github.com/kataras/iris/v12/cache" - // view - "github.com/kataras/iris/v12/view" - // i18n + "github.com/kataras/iris/v12/hero" "github.com/kataras/iris/v12/i18n" - // handlers used in `Default` function requestLogger "github.com/kataras/iris/v12/middleware/logger" "github.com/kataras/iris/v12/middleware/recover" + "github.com/kataras/iris/v12/view" "github.com/kataras/golog" "gopkg.in/yaml.v3" @@ -274,6 +264,7 @@ func (app *Application) ConfigurationReadOnly() context.ConfigurationReadOnly { // - "info" // - "debug" // Usage: app.Logger().SetLevel("error") +// Or set the level through Configurartion's LogLevel or WithLogLevel functional option. // Defaults to "info" level. // // Callers can use the application's logger which is @@ -745,6 +736,12 @@ func (app *Application) Build() error { // start := time.Now() app.builded = true // even if fails. + // check if a prior app.Logger().SetLevel called and if not + // then set the defined configuration's log level. + if app.logger.Level == golog.InfoLevel /* the default level */ { + app.logger.SetLevel(app.config.LogLevel) + } + rp := errgroup.New("Application Builder") rp.Err(app.APIBuilder.GetReporter()) @@ -1028,14 +1025,13 @@ func (app *Application) Listen(hostPort string, withOrWithout ...Configurator) e // the following runners: // `Listener`, `Server`, `Addr`, `TLS`, `AutoTLS` and `Raw`. func (app *Application) Run(serve Runner, withOrWithout ...Configurator) error { - // first Build because it doesn't need anything from configuration, - // this gives the user the chance to modify the router inside a configurator as well. + app.Configure(withOrWithout...) + if err := app.Build(); err != nil { app.logger.Error(err) return err } - app.Configure(withOrWithout...) app.tryStartTunneling() if len(app.Hosts) > 0 {