Skip to content

Instantly share code, notes, and snippets.

@XUJiahua
Created October 22, 2020 07:59
Show Gist options
  • Save XUJiahua/cf3bd770c05c0b03e6e8be2ac80860c7 to your computer and use it in GitHub Desktop.
Save XUJiahua/cf3bd770c05c0b03e6e8be2ac80860c7 to your computer and use it in GitHub Desktop.
structured logging using logrus/context
package main
import (
"context"
"encoding/json"
"github.com/google/uuid"
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
"github.com/sirupsen/logrus"
"log"
"math/rand"
"net/http"
"time"
)
func init() {
// 全局设置
logrus.SetFormatter(&logrus.JSONFormatter{})
//logrus.SetReportCaller(true)
}
// model
type Product struct {
ID string
Name string
Price float64
}
// biz logic
func Do(ctx context.Context, userID, productID string) (*Product, error) {
ctxlogrus.Extract(ctx).Info("do biz logic")
// pretend to read user
userType := "admin"
if len(userID) >= 3 {
userType = "normal"
}
// add new fields
ctxlogrus.AddFields(ctx, map[string]interface{}{
"userType": userType,
})
product, err := GetProductByID(ctx, productID)
if err != nil {
return nil, err
}
// 1~99原价,100号以后涨价
if len(userID) >= 3 {
product.Price *= 1.1
}
ctxlogrus.Extract(ctx).Infof("product price: %v", product.Price)
return product, nil
}
// mock read db
func GetProductByID(ctx context.Context, productID string) (*Product, error) {
ctxlogrus.Extract(ctx).Info("get product from db")
ms := rand.Intn(5) * 1000
time.Sleep(time.Duration(ms) * time.Millisecond)
return &Product{
ID: productID,
Name: "cat",
Price: 100,
}, nil
}
// http handler
type productHandler struct {
}
func (h *productHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
userID := r.URL.Query().Get("uid")
productID := r.URL.Query().Get("pid")
// prepare context
// StandardLogger 是全局的logger
// logrus.New() 会创建新的logger,需要另外设置formatter
ctx := ctxlogrus.ToContext(r.Context(), logrus.NewEntry(logrus.StandardLogger()))
ctxlogrus.AddFields(ctx, map[string]interface{}{
"requestID": uuid.New().String(),
"userID": userID,
"productID": productID,
})
product, err := Do(ctx, userID, productID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
encoder := json.NewEncoder(w)
_ = encoder.Encode(product)
}
// demo
// go run .
// curl http://localhost:8080/product?pid=10&uid=10
// curl http://localhost:8080/product?pid=10&uid=100
func main() {
http.Handle("/product", new(productHandler))
log.Fatal(http.ListenAndServe(":8080", nil))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment