{"id":13601217,"url":"https://github.com/gin-contrib/zap","last_synced_at":"2025-05-14T10:10:43.638Z","repository":{"id":38427405,"uuid":"79403864","full_name":"gin-contrib/zap","owner":"gin-contrib","description":"Alternative logging through zap","archived":false,"fork":false,"pushed_at":"2024-09-21T06:22:52.000Z","size":128,"stargazers_count":490,"open_issues_count":2,"forks_count":75,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-29T15:22:41.433Z","etag":null,"topics":["gin","gin-gonic","gin-middleware"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gin-contrib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-19T01:45:45.000Z","updated_at":"2024-10-26T18:41:52.000Z","dependencies_parsed_at":"2023-01-31T00:45:19.519Z","dependency_job_id":"4281dbe4-0885-4cea-86c7-8abb9097dea8","html_url":"https://github.com/gin-contrib/zap","commit_stats":{"total_commits":114,"total_committers":16,"mean_commits":7.125,"dds":"0.20175438596491224","last_synced_commit":"a7617b97c91ba8abb51293c83213f2ae3bcc7b9b"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gin-contrib%2Fzap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gin-contrib%2Fzap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gin-contrib%2Fzap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gin-contrib%2Fzap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gin-contrib","download_url":"https://codeload.github.com/gin-contrib/zap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248441947,"owners_count":21104107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gin","gin-gonic","gin-middleware"],"created_at":"2024-08-01T18:00:58.768Z","updated_at":"2025-04-11T16:40:02.055Z","avatar_url":"https://github.com/gin-contrib.png","language":"Go","funding_links":[],"categories":["Go","Log"],"sub_categories":[],"readme":"# zap\n\n[![Run Tests](https://github.com/gin-contrib/zap/actions/workflows/go.yml/badge.svg)](https://github.com/gin-contrib/zap/actions/workflows/go.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/gin-contrib/zap)](https://goreportcard.com/report/github.com/gin-contrib/zap)\n[![GoDoc](https://godoc.org/github.com/gin-contrib/zap?status.svg)](https://godoc.org/github.com/gin-contrib/zap)\n[![Join the chat at https://gitter.im/gin-gonic/gin](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gin-gonic/gin)\n\nAlternative logging through [zap](https://github.com/uber-go/zap). Thanks for [Pull Request](https://github.com/gin-gonic/contrib/pull/129) from [@yezooz](https://github.com/yezooz)\n\n## Requirement\n\nRequire Go **1.19** or later.\n\n## Usage\n\n### Start using it\n\nDownload and install it:\n\n```sh\ngo get github.com/gin-contrib/zap\n```\n\nImport it in your code:\n\n```go\nimport \"github.com/gin-contrib/zap\"\n```\n\n## Example\n\nSee the [example](_example/example01/main.go).\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"time\"\n\n  ginzap \"github.com/gin-contrib/zap\"\n  \"github.com/gin-gonic/gin\"\n  \"go.uber.org/zap\"\n)\n\nfunc main() {\n  r := gin.New()\n\n  logger, _ := zap.NewProduction()\n\n  // Add a ginzap middleware, which:\n  //   - Logs all requests, like a combined access and error log.\n  //   - Logs to stdout.\n  //   - RFC3339 with UTC time format.\n  r.Use(ginzap.Ginzap(logger, time.RFC3339, true))\n\n  // Logs all panic to error log\n  //   - stack means whether output the stack info.\n  r.Use(ginzap.RecoveryWithZap(logger, true))\n\n  // Example ping request.\n  r.GET(\"/ping\", func(c *gin.Context) {\n    c.String(200, \"pong \"+fmt.Sprint(time.Now().Unix()))\n  })\n\n  // Example when panic happen.\n  r.GET(\"/panic\", func(c *gin.Context) {\n    panic(\"An unexpected error happen!\")\n  })\n\n  // Listen and Server in 0.0.0.0:8080\n  r.Run(\":8080\")\n}\n```\n\n## Skip logging\n\nWhen you want to skip logging for specific path,\nplease use GinzapWithConfig\n\n```go\nr.Use(GinzapWithConfig(utcLogger, \u0026Config{\n  TimeFormat: time.RFC3339,\n  UTC: true,\n  SkipPaths: []string{\"/no_log\"},\n}))\n```\n\n## Custom Zap fields\n\nexample for custom log request body, response request ID or log [Open Telemetry](https://opentelemetry.io/) TraceID.\n\n```go\nfunc main() {\n  r := gin.New()\n\n  logger, _ := zap.NewProduction()\n\n  r.Use(ginzap.GinzapWithConfig(logger, \u0026ginzap.Config{\n    UTC:        true,\n    TimeFormat: time.RFC3339,\n    Context: ginzap.Fn(func(c *gin.Context) []zapcore.Field {\n      fields := []zapcore.Field{}\n      // log request ID\n      if requestID := c.Writer.Header().Get(\"X-Request-Id\"); requestID != \"\" {\n        fields = append(fields, zap.String(\"request_id\", requestID))\n      }\n\n      // log trace and span ID\n      if trace.SpanFromContext(c.Request.Context()).SpanContext().IsValid() {\n        fields = append(fields, zap.String(\"trace_id\", trace.SpanFromContext(c.Request.Context()).SpanContext().TraceID().String()))\n        fields = append(fields, zap.String(\"span_id\", trace.SpanFromContext(c.Request.Context()).SpanContext().SpanID().String()))\n      }\n\n      // log request body\n      var body []byte\n      var buf bytes.Buffer\n      tee := io.TeeReader(c.Request.Body, \u0026buf)\n      body, _ = io.ReadAll(tee)\n      c.Request.Body = io.NopCloser(\u0026buf)\n      fields = append(fields, zap.String(\"body\", string(body)))\n\n      return fields\n    }),\n  }))\n\n  // Example ping request.\n  r.GET(\"/ping\", func(c *gin.Context) {\n    c.Writer.Header().Add(\"X-Request-Id\", \"1234-5678-9012\")\n    c.String(200, \"pong \"+fmt.Sprint(time.Now().Unix()))\n  })\n\n  r.POST(\"/ping\", func(c *gin.Context) {\n    c.Writer.Header().Add(\"X-Request-Id\", \"9012-5678-1234\")\n    c.String(200, \"pong \"+fmt.Sprint(time.Now().Unix()))\n  })\n\n  // Listen and Server in 0.0.0.0:8080\n  if err := r.Run(\":8080\"); err != nil {\n    panic(err)\n  }\n}\n```\n\n## Custom `skipper` function\n\nExample for custom `skipper` function\n\n```go\nr.Use(GinzapWithConfig(logger, \u0026Config{\n  TimeFormat: time.RFC3339,\n  UTC: true,\n  Skipper: func(c *gin.Context) bool {\n    return c.Request.URL.Path == \"/ping\" \u0026\u0026 c.Request.Method == \"GET\"\n  },\n}))\n```\n\nFull example\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"time\"\n\n  ginzap \"github.com/gin-contrib/zap\"\n\n  \"github.com/gin-gonic/gin\"\n  \"go.uber.org/zap\"\n)\n\nfunc main() {\n  r := gin.New()\n\n  logger, _ := zap.NewProduction()\n\n  r.Use(ginzap.GinzapWithConfig(logger, \u0026ginzap.Config{\n    UTC:        true,\n    TimeFormat: time.RFC3339,\n    Skipper: func(c *gin.Context) bool {\n      return c.Request.URL.Path == \"/ping\" \u0026\u0026 c.Request.Method == \"GET\"\n    },\n  }))\n\n  // Example ping request.\n  r.GET(\"/ping\", func(c *gin.Context) {\n    c.Writer.Header().Add(\"X-Request-Id\", \"1234-5678-9012\")\n    c.String(200, \"pong \"+fmt.Sprint(time.Now().Unix()))\n  })\n\n  r.POST(\"/ping\", func(c *gin.Context) {\n    c.Writer.Header().Add(\"X-Request-Id\", \"9012-5678-1234\")\n    c.String(200, \"pong \"+fmt.Sprint(time.Now().Unix()))\n  })\n\n  // Listen and Server in 0.0.0.0:8080\n  if err := r.Run(\":8080\"); err != nil {\n    panic(err)\n  }\n}\n```\n\n## Custom `SkipPathRegexps` function\n\nExample for custom `SkipPathRegexps` function\n\n```go\nrxURL := regexp.MustCompile(`^/ping\\s*`)\nr.Use(ginzap.GinzapWithConfig(logger, \u0026ginzap.Config{\n  UTC:             true,\n  TimeFormat:      time.RFC3339,\n  SkipPathRegexps: []*regexp.Regexp{rxURL},\n}))\n```\n\nFull example\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"regexp\"\n  \"time\"\n\n  ginzap \"github.com/gin-contrib/zap\"\n\n  \"github.com/gin-gonic/gin\"\n  \"go.uber.org/zap\"\n)\n\nfunc main() {\n  r := gin.New()\n\n  logger, _ := zap.NewProduction()\n  rxURL := regexp.MustCompile(`^/ping\\s*`)\n\n  r.Use(ginzap.GinzapWithConfig(logger, \u0026ginzap.Config{\n    UTC:             true,\n    TimeFormat:      time.RFC3339,\n    SkipPathRegexps: []*regexp.Regexp{rxURL},\n  }))\n\n  // Example ping request.\n  r.GET(\"/ping1234\", func(c *gin.Context) {\n    c.String(200, \"pong \"+fmt.Sprint(time.Now().Unix()))\n  })\n\n  // Listen and Server in 0.0.0.0:8080\n  if err := r.Run(\":8080\"); err != nil {\n    panic(err)\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgin-contrib%2Fzap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgin-contrib%2Fzap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgin-contrib%2Fzap/lists"}