Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding custom attribute support for http middleware #26

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

manasachi
Copy link
Collaborator

@manasachi manasachi commented Mar 11, 2025

This PR allows extra attributes to be assigned to the logger.

  • CustomAttributes struct:

    • If specified, allows users to specify an initializer and assigner function. The initializer should initialize the custom attributes and return then as a map[string]interface{}.
    • At the end of ServeHTTP(), the assigner function takes those initialized attributes as a parameter and updates values as needed
  • loggingMiddleware takes source as a field. If specified, it is assigned. Otherwise, the default is "ApiRequestLog"

@manasachi manasachi marked this pull request as ready for review March 12, 2025 16:33
customWriter := &responseWriter{ResponseWriter: w}
// If any fields in CustomAttributes are nil, do not call them to avoid errors
addExtraAttributes := validateCustomAttributes(&l.customAttributeAssigner)
var extraAttributes map[string]interface{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will be initialized to the zero value, correct? For maps it's nil. So this should just be initialized to an empty map

l.LogRequestEnd(ctx, r, "finished call", customWriter.statusCode, latency, updatedAttrs)
}

func (l *loggingMiddleware) BuildLoggingAttributes(ctx context.Context, r *http.Request, extra ...interface{}) []interface{} {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any particular reason why extra changed to an interface? Could you just keep the map[string]interface{} type throughout?

type loggingFunc func(w http.ResponseWriter, r *http.Request, attrs map[string]interface{}) map[string]interface{}
type CustomAttributes struct {
AttributeInitializer *initFunc // sets keys for custom attributes at the beginning of ServeHTTP()
AttributeAssigner *loggingFunc // assigns values for custom attributes after request has completed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we provide default Attribute initializers and assigners?

now: time.Now,
logger: *logger,
source: source,
customAttributeAssigner: customAttributeAssigner,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you support the initializer and assigner funcs to be nil? If not then you should assign them to default functions if not provided


var updatedAttrs map[string]interface{}
if addExtraAttributes {
updatedAttrs = (l.customAttributeAssigner.AttributeAssigner)(w, r, extraAttributes)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we pass in the original http.ResponseWriter rather than the customWriter here?

}

// sets default source "ApiRequestLog"
func setSourceIfEmtpy(source *string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

type CustomAttributes struct {
AttributeInitializer initFunc // sets keys for custom attributes at the beginning of ServeHTTP()
AttributeAssigner loggingFunc // assigns values for custom attributes after request has completed
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming the struct to something like "AttributeManager" and the methods to be along the lines of "Initialize" and "Assign"

type CustomAttributes struct {
AttributeInitializer initFunc // sets keys for custom attributes at the beginning of ServeHTTP()
AttributeAssigner loggingFunc // assigns values for custom attributes after request has completed
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we just set the keys and assign the values in the same function after the request has completed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants