1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-18 18:37:05 +00:00

Update to 8.1.0 - a new logger implemented as a solution for https://github.com/kataras/iris/issues/680

Former-commit-id: 765b43602655fad7f525ca7a5f7f297a6167d075
This commit is contained in:
kataras
2017-07-26 15:30:20 +03:00
parent 726d89fd1b
commit 345e7280a1
14 changed files with 78 additions and 50 deletions

View File

@@ -7,7 +7,7 @@ go:
- tip - tip
go_import_path: github.com/kataras/iris go_import_path: github.com/kataras/iris
install: install:
- go get ./... # for iris-contrib/httpexpect and sirupsen/logrus - go get ./... # for iris-contrib/httpexpect and kataras/golog
script: script:
- go test -v -cover ./... - go test -v -cover ./...
after_script: after_script:

View File

@@ -13,10 +13,46 @@
### Should I upgrade my Iris? ### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready. Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes. > Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`. **How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
# We, 26 July 2017 | v8.1.0
The `app.Logger() *logrus.Logger` was replaced with a custom implementation [[golog](https://github.com/kataras/golog)], it's compatible with the [logrus](https://github.com/sirupsen/logrus) package and other open-source golang loggers as well, because of that: https://github.com/kataras/iris/issues/680#issuecomment-316184570.
The API didn't change much except these:
- the new implementation does not recognise `Fatal` and `Panic` because, actually, iris never panics
- the old `app.Logger().Out = io.Writer` should be written as `app.Logger().SetOutput(io.Writer)`
The new implementation, [golog](https://github.com/kataras/golog) is more featured
and it completes more use cases than the before external implementation.
At general you have to know that the low-level relative fields and functions are actually inside `app.Logger().Printer` object, i.e: `app.Logger().Printer.Output` to get the `io.Writer` or `app.Logger().Printer.AddOuput/SetOutput` to set or add more output(`io.Writer`) targets.
### Integration
I understand that many of you may use logrus outside of Iris too. To integrate an external `logrus` logger just
`Install` it-- all print operations will be handled by the provided `logrus instance`.
```go
import (
"github.com/kataras/iris"
"github.com/sirupsen/logrus"
)
package main(){
app := iris.New()
app.Logger().Install(logrus.StandardLogger()) // the package-level logrus instance
// [...]
}
```
For more information about our new logger please navigate to: https://github.com/kataras/golog - contributions are welcomed as well!
# Sa, 23 July 2017 | v8.0.7 # Sa, 23 July 2017 | v8.0.7
Fix [It's true that with UseGlobal the "/path1.txt" route call the middleware but cause the prepend, the order is inversed](https://github.com/kataras/iris/issues/683#issuecomment-317229068) Fix [It's true that with UseGlobal the "/path1.txt" route call the middleware but cause the prepend, the order is inversed](https://github.com/kataras/iris/issues/683#issuecomment-317229068)

View File

@@ -17,7 +17,7 @@ Iris is a fast, simple and efficient micro web framework for Go. It provides a b
### 📑 Table of contents ### 📑 Table of contents
* [Installation](#-installation) * [Installation](#-installation)
* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#sa-23-july-2017--v807) * [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#we-26-july-2017--v810)
* [Learn](#-learn) * [Learn](#-learn)
* [HTTP Listening](_examples/#http-listening) * [HTTP Listening](_examples/#http-listening)
* [Configuration](_examples/#configuration) * [Configuration](_examples/#configuration)
@@ -339,7 +339,7 @@ Thank You for your trust!
### 📌 Version ### 📌 Version
Current: **8.0.7** Current: **8.1.0**
Each new release is pushed to the master. It stays there until the next version. When a next version is released then the previous version goes to its own branch with `gopkg.in` as its import path (and its own vendor folder), in order to keep it working "for-ever". Each new release is pushed to the master. It stays there until the next version. When a next version is released then the previous version goes to its own branch with `gopkg.in` as its import path (and its own vendor folder), in order to keep it working "for-ever".

View File

@@ -3,7 +3,6 @@ package main
import ( import (
"bytes" "bytes"
stdContext "context" stdContext "context"
"fmt"
"strings" "strings"
"testing" "testing"
"time" "time"
@@ -14,7 +13,7 @@ import (
func logger(app *iris.Application) *bytes.Buffer { func logger(app *iris.Application) *bytes.Buffer {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
app.Logger().Out = buf app.Logger().SetOutput(buf)
// disable the "Now running at...." in order to have a clean log of the error. // disable the "Now running at...." in order to have a clean log of the error.
// we could attach that on `Run` but better to keep things simple here. // we could attach that on `Run` but better to keep things simple here.
@@ -41,20 +40,12 @@ func TestListenAddr(t *testing.T) {
t.Fatalf("expecting err to be `iris.ErrServerClosed` but got: %v", err) t.Fatalf("expecting err to be `iris.ErrServerClosed` but got: %v", err)
} }
// println(log.Bytes()) expectedMessage := iris.ErrServerClosed.Error()
// println(len(log.Bytes()))
expected := fmt.Sprintln("\"" + iris.ErrServerClosed.Error() + "\" ") if got := log.String(); !strings.Contains(got, expectedMessage) {
expected = strings.TrimSpace(expected) t.Fatalf("expecting to log to contains the:\n'%s'\ninstead of:\n'%s'", expectedMessage, got)
// println([]byte(expected))
// println(len([]byte(expected)))
got := log.String()
got = strings.Split(got, "msg=")[1]
got = strings.TrimSpace(got)
if expected != got {
t.Fatalf("expecting to log the:\n'%s'\ninstead of:\n'%s'", expected, got)
} }
} }
func TestListenAddrWithoutServerErr(t *testing.T) { func TestListenAddrWithoutServerErr(t *testing.T) {

View File

@@ -18,7 +18,8 @@ func main() {
Method: true, Method: true,
// Path displays the request path // Path displays the request path
Path: true, Path: true,
// Columns: true,
//Columns: true,
// if !empty then its contents derives from `ctx.Values().Get("logger_message") // if !empty then its contents derives from `ctx.Values().Get("logger_message")
// will be added to the logs. // will be added to the logs.
@@ -57,6 +58,6 @@ func main() {
// http://localhost:8080/2 // http://localhost:8080/2
// http://lcoalhost:8080/notfoundhere // http://lcoalhost:8080/notfoundhere
// see the output on the console. // see the output on the console.
app.Run(iris.Addr(":8080")) app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
} }

View File

@@ -36,7 +36,7 @@ func main() {
// http://localhost:8080/1 // http://localhost:8080/1
// http://localhost:8080/2 // http://localhost:8080/2
// http://lcoalhost:8080/notfoundhere // http://lcoalhost:8080/notfoundhere
app.Run(iris.Addr(":8080")) app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
} }
// get a filename based on the date, file logs works that way the most times // get a filename based on the date, file logs works that way the most times

View File

@@ -32,11 +32,11 @@ func main() {
app := iris.New() app := iris.New()
// attach the file as logger, remember, iris' app logger is just an io.Writer. // attach the file as logger, remember, iris' app logger is just an io.Writer.
app.Logger().Out = newLogFile() app.Logger().SetOutput(newLogFile())
app.Get("/", func(ctx context.Context) { app.Get("/", func(ctx context.Context) {
// for the sake of simplicity, in order see the logs at the ./_today_.txt // for the sake of simplicity, in order see the logs at the ./_today_.txt
ctx.Application().Logger().Infoln("Request path: " + ctx.Path()) ctx.Application().Logger().Info("Request path: " + ctx.Path())
ctx.Writef("hello") ctx.Writef("hello")
}) })
@@ -44,7 +44,7 @@ func main() {
// and open the ./logs.txt file // and open the ./logs.txt file
if err := app.Run(iris.Addr(":8080"), iris.WithoutBanner); err != nil { if err := app.Run(iris.Addr(":8080"), iris.WithoutBanner); err != nil {
if err != iris.ErrServerClosed { if err != iris.ErrServerClosed {
app.Logger().Warnln("Shutdown with error: " + err.Error()) app.Logger().Warn("Shutdown with error: " + err.Error())
} }
} }
} }

View File

@@ -40,7 +40,7 @@ func main() {
// using the go v1.8's HTTP/2 Push. // using the go v1.8's HTTP/2 Push.
// Note that you have to listen using ListenTLS in order this to work. // Note that you have to listen using ListenTLS in order this to work.
if err := ctx.ResponseWriter().Push("/js/chat.js", nil); err != nil { if err := ctx.ResponseWriter().Push("/js/chat.js", nil); err != nil {
ctx.Application().Logger().Warnln(err.Error()) ctx.Application().Logger().Warn(err.Error())
} }
ctx.ViewData("", clientPage{"Client Page", ctx.Host()}) ctx.ViewData("", clientPage{"Client Page", ctx.Host()})
ctx.View("client.html") ctx.View("client.html")

View File

@@ -4,7 +4,7 @@ import (
"io" "io"
"net/http" "net/http"
"github.com/sirupsen/logrus" "github.com/kataras/golog"
) )
// Application is the context's owner. // Application is the context's owner.
@@ -14,8 +14,8 @@ type Application interface {
// ConfigurationReadOnly returns all the available configuration values can be used on a request. // ConfigurationReadOnly returns all the available configuration values can be used on a request.
ConfigurationReadOnly() ConfigurationReadOnly ConfigurationReadOnly() ConfigurationReadOnly
// Logger returns the logrus logger instance(pointer) that is being used inside the "app". // Logger returns the golog logger instance(pointer) that is being used inside the "app".
Logger() *logrus.Logger Logger() *golog.Logger
// View executes and write the result of a template file to the writer. // View executes and write the result of a template file to the writer.
// //

View File

@@ -2231,7 +2231,7 @@ func (ctx *context) BeginTransaction(pipe func(t *Transaction)) {
t := newTransaction(ctx) // it calls this *context, so the overriding with a new pool's New of context.Context wil not work here. t := newTransaction(ctx) // it calls this *context, so the overriding with a new pool's New of context.Context wil not work here.
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
ctx.Application().Logger().Warnln(errTransactionInterrupted.Format(err).Error()) ctx.Application().Logger().Warn(errTransactionInterrupted.Format(err).Error())
// complete (again or not , doesn't matters) the scope without loud // complete (again or not , doesn't matters) the scope without loud
t.Complete(nil) t.Complete(nil)
// we continue as normal, no need to return here* // we continue as normal, no need to return here*

2
doc.go
View File

@@ -35,7 +35,7 @@ Source code and other details for the project are available at GitHub:
Current Version Current Version
8.0.7 8.1.0
Installation Installation

33
iris.go
View File

@@ -10,7 +10,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/sirupsen/logrus" "github.com/kataras/golog"
// context for the handlers // context for the handlers
"github.com/kataras/iris/context" "github.com/kataras/iris/context"
@@ -33,7 +33,7 @@ import (
const ( const (
// Version is the current version number of the Iris Web Framework. // Version is the current version number of the Iris Web Framework.
Version = "8.0.7" Version = "8.1.0"
) )
// HTTP status codes as registered with IANA. // HTTP status codes as registered with IANA.
@@ -137,8 +137,8 @@ type Application struct {
// all fields defaults to something that is working, developers don't have to set it. // all fields defaults to something that is working, developers don't have to set it.
config *Configuration config *Configuration
// the logrus logger instance, defaults to "Info" level messages (all except "Debug") // the golog logger instance, defaults to "Info" level messages (all except "Debug")
logger *logrus.Logger logger *golog.Logger
// view engine // view engine
view view.View view view.View
@@ -163,7 +163,7 @@ func New() *Application {
app := &Application{ app := &Application{
config: &config, config: &config,
logger: logrus.New(), logger: golog.Default,
APIBuilder: router.NewAPIBuilder(), APIBuilder: router.NewAPIBuilder(),
Router: router.NewRouter(), Router: router.NewRouter(),
} }
@@ -207,20 +207,19 @@ func (app *Application) ConfigurationReadOnly() context.ConfigurationReadOnly {
// These are the different logging levels. You can set the logging level to log // These are the different logging levels. You can set the logging level to log
// on the application 's instance of logger, obtained with `app.Logger()`. // on the application 's instance of logger, obtained with `app.Logger()`.
// //
// These are conversions from logrus. // These are conversions from golog.
const ( const (
// NoLog level, logs nothing. // NoLog level, logs nothing.
// It's the logrus' `PanicLevel` but it never used inside iris so it will never log. NoLog = golog.DisableLevel
NoLog = logrus.PanicLevel
// ErrorLevel level. Logs. Used for errors that should definitely be noted. // ErrorLevel level. Logs. Used for errors that should definitely be noted.
// Commonly used for hooks to send errors to an error tracking service. // Commonly used for hooks to send errors to an error tracking service.
ErrorLevel = logrus.ErrorLevel ErrorLevel = golog.ErrorLevel
// WarnLevel level. Non-critical entries that deserve eyes. // WarnLevel level. Non-critical entries that deserve eyes.
WarnLevel = logrus.WarnLevel WarnLevel = golog.WarnLevel
) )
// Logger returns the logrus logger instance(pointer) that is being used inside the "app". // Logger returns the golog logger instance(pointer) that is being used inside the "app".
func (app *Application) Logger() *logrus.Logger { func (app *Application) Logger() *golog.Logger {
return app.logger return app.logger
} }
@@ -264,13 +263,13 @@ func (app *Application) RegisterView(viewEngine view.Engine) {
func (app *Application) View(writer io.Writer, filename string, layout string, bindingData interface{}) error { func (app *Application) View(writer io.Writer, filename string, layout string, bindingData interface{}) error {
if app.view.Len() == 0 { if app.view.Len() == 0 {
err := errors.New("view engine is missing, use `RegisterView`") err := errors.New("view engine is missing, use `RegisterView`")
app.Logger().Errorln(err) app.Logger().Error(err)
return err return err
} }
err := app.view.ExecuteWriter(writer, filename, layout, bindingData) err := app.view.ExecuteWriter(writer, filename, layout, bindingData)
if err != nil { if err != nil {
app.Logger().Errorln(err) app.Logger().Error(err)
} }
return err return err
} }
@@ -328,7 +327,7 @@ func (app *Application) NewHost(srv *http.Server) *host.Supervisor {
// check if different ErrorLog provided, if not bind it with the framework's logger // check if different ErrorLog provided, if not bind it with the framework's logger
if srv.ErrorLog == nil { if srv.ErrorLog == nil {
srv.ErrorLog = log.New(app.logger.Out, "[HTTP Server] ", 0) srv.ErrorLog = log.New(app.logger.Printer.Output, "[HTTP Server] ", 0)
} }
if srv.Addr == "" { if srv.Addr == "" {
@@ -352,7 +351,7 @@ func (app *Application) NewHost(srv *http.Server) *host.Supervisor {
if !app.config.DisableStartupLog { if !app.config.DisableStartupLog {
// show the available info to exit from app. // show the available info to exit from app.
su.RegisterOnServe(host.WriteStartupLogOnServe(app.logger.Out)) // app.logger.Writer -> Info su.RegisterOnServe(host.WriteStartupLogOnServe(app.logger.Printer.Output)) // app.logger.Writer -> Info
} }
if !app.config.DisableInterruptHandler { if !app.config.DisableInterruptHandler {
@@ -543,7 +542,7 @@ func (app *Application) Run(serve Runner, withOrWithout ...Configurator) error {
// this will block until an error(unless supervisor's DeferFlow called from a Task). // this will block until an error(unless supervisor's DeferFlow called from a Task).
err := serve(app) err := serve(app)
if err != nil { if err != nil {
app.Logger().Errorln(err) app.Logger().Error(err)
} }
return err return err
} }

View File

@@ -79,14 +79,15 @@ func (l *requestLoggerMiddleware) ServeHTTP(ctx context.Context) {
logFunc(endTime, latency, status, ip, method, path, message) logFunc(endTime, latency, status, ip, method, path, message)
return return
} }
endTimeFormatted := endTime.Format("2006/01/02 - 15:04:05")
if l.config.Columns { if l.config.Columns {
endTimeFormatted := endTime.Format("2006/01/02 - 15:04:05")
output := Columnize(endTimeFormatted, latency, status, ip, method, path, message) output := Columnize(endTimeFormatted, latency, status, ip, method, path, message)
ctx.Application().Logger().Out.Write([]byte(output)) ctx.Application().Logger().Printer.Output.Write([]byte(output))
return return
} }
// no new line, the framework's logger is responsible how to render each log. // no new line, the framework's logger is responsible how to render each log.
line := fmt.Sprintf("%s | %v %4v %s %s %s", endTimeFormatted, status, latency, ip, method, path) line := fmt.Sprintf("%v %4v %s %s %s", status, latency, ip, method, path)
if message != nil { if message != nil {
line += fmt.Sprintf(" %v", message) line += fmt.Sprintf(" %v", message)
} }

View File

@@ -46,7 +46,7 @@ func New() context.Handler {
logMessage += fmt.Sprintf("At Request: %s\n", getRequestLogs(ctx)) logMessage += fmt.Sprintf("At Request: %s\n", getRequestLogs(ctx))
logMessage += fmt.Sprintf("Trace: %s\n", err) logMessage += fmt.Sprintf("Trace: %s\n", err)
logMessage += fmt.Sprintf("\n%s", stacktrace) logMessage += fmt.Sprintf("\n%s", stacktrace)
ctx.Application().Logger().Warnln(logMessage) ctx.Application().Logger().Warn(logMessage)
ctx.StatusCode(500) ctx.StatusCode(500)
ctx.StopExecution() ctx.StopExecution()