sloghttp

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 1, 2024 License: MIT Imports: 7 Imported by: 1

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AttrCollection

func AttrCollection(next http.Handler) http.Handler

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

func ExtractAttrCollection(ctx context.Context, _ time.Time, _ slog.Level, _ string) []slog.Attr

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:

func With

func With(ctx context.Context, args ...any) context.Context

With adds the provided slog.Attr's to the context. If used with sloghttp.AttrCollection it will add them to the context in a way that is visible to all intermediate middlewares and functions between the collector middleware and the call to With.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL