Documentation ¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AttrCollection ¶
AttrCollection is an http middleware that collects slog.Attr from any and all later middlewares and the final http request handler, and makes them available to all middlewares and the request handler. Essentially, it lets you collect slog attributes that are discovered later in the stack (such as authentication and user ID's, derived values, attributes only discovered halfway-through the final request handler after several db queries, etc), and be able to have them be included in the log lines of other middlewares (such as a middleware that logs all requests that come in).
Requires the use of slogctx.Handler, as a wrapper or middleware around your slog formatter/sink.
Attributes are added by calls to sloghttp.With, and the attributes are then stored inside the context. All calls log that include the context will automatically have all the attributes included (ex: slogctx.Info, or slog.InfoContext).
Example ¶
package main import ( "net/http" slogctx "github.com/veqryn/slog-context" sloghttp "github.com/veqryn/slog-context/http" ) func main() { // This is our final api endpoint handler helloUserHandler := func(w http.ResponseWriter, r *http.Request) { // Stand-in for a User ID. // Add it to our middleware's context id := r.URL.Query().Get("id") // sloghttp.With will add the "id" to to the middleware, because it is a // synchronized map. It will show up in all log calls up and down the stack, // until the request sloghttp middleware exits. ctx := sloghttp.With(r.Context(), "id", id) // Log some things. Should also have both "path", "id" slogctx.Info(ctx, "saying hello...") _, _ = w.Write([]byte("Hello User #" + id)) } // This is a stand-in for a middleware that might be capturing and logging out // things like the response code, request body, response body, url, method, etc. // It doesn't have access to any of the new context objects's created within the // next handler. But it should still log with any of the attributes added to our // sloghttp.Middleware, via sloghttp.With. httpLoggingMiddleware := func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Add some logging context/baggage before the handler r = r.WithContext(sloghttp.With(r.Context(), "path", r.URL.Path)) // Call the next handler next.ServeHTTP(w, r) // Log out that we had a response. This would be where we could add // things such as the response status code, body, etc. // Should also have both "path" and "id", but not "foo". // Having "id" included in the log is the whole point of this package! slogctx.Info(r.Context(), "Response", "method", r.Method) /* { "time": "2024-04-01T00:06:11Z", "level": "INFO", "msg": "Response", "path": "/hello", "id": "24680", "method": "GET" } */ }) } // Wrap our final handler inside our middlewares. // AttrCollector -> Request Logging -> Final Endpoint Handler (helloUser) handler := sloghttp.AttrCollection( httpLoggingMiddleware( http.HandlerFunc(helloUserHandler), ), ) // Demonstrate the sloghttp middleware with a http server http.Handle("/hello", handler) err := http.ListenAndServe(":8080", nil) if err != nil { panic(err) } }
Output:
func ExtractAttrCollection ¶
ExtractAttrCollection is a slogctx Extractor that must be used with a slogctx.Handler (via slogctx.HandlerOptions) as Prependers or Appenders. It will cause the Handler to add the Attributes added by sloghttp.With to all log lines using that same context.
Example ¶
package main import ( "log/slog" "os" slogctx "github.com/veqryn/slog-context" sloghttp "github.com/veqryn/slog-context/http" ) func main() { // Create the *slogctx.Handler middleware h := slogctx.NewHandler( slog.NewJSONHandler(os.Stdout, nil), // The next or final handler in the chain &slogctx.HandlerOptions{ // Prependers will first add the any sloghttp.With attributes, // then anything else Prepended to the ctx Prependers: []slogctx.AttrExtractor{ sloghttp.ExtractAttrCollection, // our sloghttp middleware extractor slogctx.ExtractPrepended, // for all other prepended attributes }, }, ) slog.SetDefault(slog.New(h)) }
Output:
Types ¶
This section is empty.