]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/log/slog/record.go
log/slog: fix method name in docs
[gostls13.git] / src / log / slog / record.go
index 972552d5194e1778093566f9847b363e8a06fbcc..97c87019a6aff5bbee9a96c4084ab815f0737f66 100644 (file)
@@ -50,7 +50,7 @@ type Record struct {
        back []Attr
 }
 
-// NewRecord creates a Record from the given arguments.
+// NewRecord creates a [Record] from the given arguments.
 // Use [Record.AddAttrs] to add attributes to the Record.
 //
 // NewRecord is intended for logging APIs that want to support a [Handler] as
@@ -72,12 +72,12 @@ func (r Record) Clone() Record {
        return r
 }
 
-// NumAttrs returns the number of attributes in the Record.
+// NumAttrs returns the number of attributes in the [Record].
 func (r Record) NumAttrs() int {
        return r.nFront + len(r.back)
 }
 
-// Attrs calls f on each Attr in the Record.
+// Attrs calls f on each Attr in the [Record].
 // Iteration stops if f returns false.
 func (r Record) Attrs(f func(Attr) bool) {
        for i := 0; i < r.nFront; i++ {
@@ -92,38 +92,57 @@ func (r Record) Attrs(f func(Attr) bool) {
        }
 }
 
-// AddAttrs appends the given Attrs to the Record's list of Attrs.
+// AddAttrs appends the given Attrs to the [Record]'s list of Attrs.
+// It omits empty groups.
 func (r *Record) AddAttrs(attrs ...Attr) {
-       n := copy(r.front[r.nFront:], attrs)
-       r.nFront += n
+       var i int
+       for i = 0; i < len(attrs) && r.nFront < len(r.front); i++ {
+               a := attrs[i]
+               if a.Value.isEmptyGroup() {
+                       continue
+               }
+               r.front[r.nFront] = a
+               r.nFront++
+       }
        // Check if a copy was modified by slicing past the end
        // and seeing if the Attr there is non-zero.
        if cap(r.back) > len(r.back) {
                end := r.back[:len(r.back)+1][len(r.back)]
                if !end.isEmpty() {
-                       panic("copies of a slog.Record were both modified")
+                       // Don't panic; copy and muddle through.
+                       r.back = slices.Clip(r.back)
+                       r.back = append(r.back, String("!BUG", "AddAttrs unsafely called on copy of Record made without using Record.Clone"))
+               }
+       }
+       ne := countEmptyGroups(attrs[i:])
+       r.back = slices.Grow(r.back, len(attrs[i:])-ne)
+       for _, a := range attrs[i:] {
+               if !a.Value.isEmptyGroup() {
+                       r.back = append(r.back, a)
                }
        }
-       r.back = append(r.back, attrs[n:]...)
 }
 
 // Add converts the args to Attrs as described in [Logger.Log],
-// then appends the Attrs to the Record's list of Attrs.
+// then appends the Attrs to the [Record]'s list of Attrs.
+// It omits empty groups.
 func (r *Record) Add(args ...any) {
        var a Attr
        for len(args) > 0 {
                a, args = argsToAttr(args)
+               if a.Value.isEmptyGroup() {
+                       continue
+               }
                if r.nFront < len(r.front) {
                        r.front[r.nFront] = a
                        r.nFront++
                } else {
                        if r.back == nil {
-                               r.back = make([]Attr, 0, countAttrs(args))
+                               r.back = make([]Attr, 0, countAttrs(args)+1)
                        }
                        r.back = append(r.back, a)
                }
        }
-
 }
 
 // countAttrs returns the number of Attrs that would be created from args.
@@ -174,7 +193,7 @@ type Source struct {
        Line int    `json:"line"`
 }
 
-// attrs returns the non-zero fields of s as a slice of attrs.
+// group returns the non-zero fields of s as a slice of attrs.
 // It is similar to a LogValue method, but we don't want Source
 // to implement LogValuer because it would be resolved before
 // the ReplaceAttr function was called.