-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
developer
committed
Apr 4, 2024
1 parent
c4a6efb
commit d8f5506
Showing
8 changed files
with
383 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
linters-settings: | ||
gosec: | ||
confidence: low | ||
godot: | ||
exclude: | ||
# Exclude swagger comments | ||
- "@" | ||
gci: | ||
skip-generated: true | ||
cyclop: | ||
max-complexity: 15 | ||
tagliatelle: | ||
# Check the struck tag name case. | ||
case: | ||
# Use the struct field name to check the name of the struct tag. | ||
# Default: false | ||
use-field-name: true | ||
rules: | ||
# Any struct tag type can be used. | ||
# Support string case: `camel`, `pascal`, `kebab`, `snake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower` | ||
json: snake | ||
yaml: snake | ||
xml: snake | ||
|
||
linters: | ||
enable: | ||
- asasalint | ||
- bidichk | ||
- cyclop | ||
- decorder | ||
- dogsled | ||
- dupl | ||
- dupword | ||
- errcheck | ||
- errchkjson | ||
- errorlint | ||
- exhaustive | ||
- forbidigo | ||
- gocognit | ||
- goconst | ||
- gocritic | ||
- gocyclo | ||
- godot | ||
- godox | ||
- gofmt | ||
- gofumpt | ||
- goheader | ||
- goimports | ||
- gomnd | ||
- gomoddirectives | ||
- gomodguard | ||
- gosimple | ||
- gosec | ||
- govet | ||
- grouper | ||
- importas | ||
- ineffassign | ||
- interfacebloat | ||
- lll | ||
- loggercheck | ||
- maintidx | ||
- makezero | ||
- misspell | ||
- nakedret | ||
- nestif | ||
- nilnil | ||
- nlreturn | ||
- nolintlint | ||
- nonamedreturns | ||
- prealloc | ||
- predeclared | ||
- promlinter | ||
- reassign | ||
- staticcheck | ||
- stylecheck | ||
- tagliatelle | ||
- tenv | ||
- typecheck | ||
- usestdlibvars | ||
- unparam | ||
- unused | ||
- whitespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 Ronald Bell. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# PrettyLogger for Echo | ||
|
||
PrettyLogger is a middleware for the Echo web framework that enhances the visibility of server logs through color-coded and formatted output. It's designed to improve the readability of logs by highlighting different aspects of HTTP requests and responses such as status codes, method types, and data transfer sizes. | ||
|
||
![PrettyLogger Screenshot](assets/screenshot.png) | ||
|
||
## Features | ||
|
||
- **Color-Coded Output**: Uses ANSI color codes to differentiate between HTTP methods, status codes, and other log components for quick visual parsing. | ||
- **Formatted Path and Method Display**: Ensures consistent formatting for request paths and methods, including truncation with ellipses for long paths. | ||
- **Readable Data Sizes**: Converts byte counts into a more readable format (b, Kb, Mb, Gb) for both incoming and outgoing data. | ||
- **Performance Timing**: Logs the duration of each request in milliseconds, helping identify slow endpoints. | ||
|
||
## Usage | ||
|
||
To use PrettyLogger in your Echo project, follow these steps: | ||
|
||
1. Import the PrettyLogger package into your Echo application. | ||
2. Add the `Logger` function as middleware to your Echo instance. | ||
|
||
Example: | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"github.com/labstack/echo/v4" | ||
"github.com/rdbell/echo-pretty-logger" | ||
) | ||
|
||
func main() { | ||
e := echo.New() | ||
|
||
// Add PrettyLogger middleware | ||
e.Use(prettyLogger.Logger) | ||
|
||
// Define your routes | ||
e.GET("/", func(c echo.Context) error { | ||
return c.String(http.StatusOK, "Hello, World!") | ||
}) | ||
|
||
// Start server | ||
e.Start(":8080") | ||
} | ||
``` | ||
|
||
## Demo | ||
To demo PrettyLogger's capabilities, navigate to the [`example`](/example) folder within this repository and run `go run main.go` in your terminal. This command will launch an Echo server demonstrating the middleware's color-coded and formatted logging output. | ||
|
||
## Configuration | ||
|
||
Currently, PrettyLogger does not require any configuration and works out of the box by providing sensible defaults for logging HTTP requests and responses. It automatically handles different HTTP methods, status codes, and content sizes in a visually distinct manner. | ||
|
||
## Contribution | ||
|
||
Contributions are welcome! If you'd like to improve PrettyLogger or suggest new features, feel free to fork the repository, make your changes, and submit a pull request. | ||
|
||
# License | ||
|
||
This project is licensed under the MIT License. See the [LICENSE](/LICENSE) file for more details. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"crypto/rand" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net/http" | ||
|
||
"github.com/labstack/echo/v4" | ||
"github.com/labstack/echo/v4/middleware" | ||
prettylogger "github.com/rdbell/echo-pretty-logger" | ||
) | ||
|
||
const ( | ||
Kilobyte = 1024 | ||
Megabyte = 1024 * Kilobyte | ||
) | ||
|
||
func main() { | ||
// Set up a new Echo server | ||
e := echo.New() | ||
|
||
// Hello World! | ||
e.GET("/", func(c echo.Context) error { | ||
return c.String(http.StatusOK, "Hello, World!") | ||
}) | ||
|
||
// Redirect example | ||
e.GET("/redirect", func(c echo.Context) error { | ||
return c.Redirect(http.StatusMovedPermanently, "/") | ||
}) | ||
|
||
// Unauthorized example | ||
e.GET("/unauthorized", func(c echo.Context) error { | ||
return c.String(http.StatusUnauthorized, "Unauthorized") | ||
}) | ||
|
||
// POST example | ||
e.POST("/post", func(c echo.Context) error { | ||
// Return a 1MB response | ||
bb := make([]byte, Megabyte) | ||
|
||
return c.Blob(http.StatusOK, "application/octet-stream", bb) | ||
}) | ||
|
||
// Start server | ||
go func() { | ||
err := e.Start(":8080") | ||
if err != nil { | ||
log.Fatalf("Failed to start server: %v", err) | ||
} | ||
}() | ||
|
||
// Wait for server to start | ||
for { | ||
_, err := http.Get("http://localhost:8080/") | ||
if err == nil { | ||
break | ||
} | ||
} | ||
|
||
// Conditional Logger Middleware | ||
usePrettyLogger := false | ||
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { | ||
return func(c echo.Context) error { | ||
// Condition to decide which logger to use | ||
if usePrettyLogger { | ||
return prettylogger.Logger(next)(c) | ||
} | ||
|
||
return middleware.Logger()(next)(c) | ||
} | ||
}) | ||
|
||
// Default logger | ||
log.Println("\n\n\nBefore:") | ||
testRequests() | ||
|
||
// PettyLogger | ||
log.Println("\n\n\nAfter:") | ||
usePrettyLogger = true | ||
testRequests() | ||
} | ||
|
||
func makeRequest(client *http.Client, method, url string) error { | ||
var request *http.Request | ||
var err error | ||
|
||
// Handle different request methods | ||
switch method { | ||
case http.MethodPost: | ||
// Generate a byte slice to use as the body of the POST request | ||
data := make([]byte, Megabyte) | ||
if _, err := rand.Read(data); err != nil { | ||
return fmt.Errorf("failed to generate data for POST: %w", err) | ||
} | ||
|
||
// Use the byte slice as the body of the POST request | ||
dataReader := bytes.NewReader(data) | ||
request, err = http.NewRequest(http.MethodPost, url, dataReader) | ||
if err != nil { | ||
return fmt.Errorf("failed to create POST request: %w", err) | ||
} | ||
case http.MethodGet, http.MethodConnect: | ||
request, err = http.NewRequest(method, url, nil) | ||
if err != nil { | ||
return fmt.Errorf("failed to create %s request: %w", method, err) | ||
} | ||
default: | ||
return fmt.Errorf("unsupported method: %s", method) | ||
} | ||
|
||
// Send the request | ||
response, err := client.Do(request) | ||
if err != nil { | ||
return fmt.Errorf("failed to send %s request: %w", method, err) | ||
} | ||
defer response.Body.Close() | ||
|
||
// Read and discard the response body | ||
_, err = io.Copy(io.Discard, response.Body) | ||
if err != nil { | ||
return fmt.Errorf("failed to read the response body: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testRequests() { | ||
// Setup client | ||
client := &http.Client{} | ||
|
||
// List of URLs to test along with their request method | ||
requests := map[string]string{ | ||
"http://localhost:8080/": http.MethodGet, | ||
"http://localhost:8080/redirect": http.MethodGet, | ||
"http://localhost:8080/unauthorized": http.MethodGet, | ||
"http://localhost:8080/not_found": http.MethodConnect, | ||
"http://localhost:8080/post": http.MethodPost, | ||
} | ||
|
||
// Iterate over the requests and make them | ||
for url, method := range requests { | ||
err := makeRequest(client, method, url) | ||
if err != nil { | ||
log.Fatalf("Failed to make request to %s: %v", url, err) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.