@@ -114,15 +114,21 @@ pub fn (r Record) prepend(field ...Field) Record {
114114 }
115115}
116116
117+ // add adds new field with given name and value to a record and returns the modified record.
118+ pub fn (r Record) add (name string , value Value) Record {
119+ return r.append (field (name, value))
120+ }
121+
117122// field adds new field with given name and value to a record and returns the modified record.
123+ @[deprecated: 'use add() instead' ]
118124pub fn (r Record) field (name string , value Value) Record {
119125 return r.append (Field{ name: name, value: value })
120126}
121127
122128// message adds new message field to a record and returns the modified record.
123- // This is a shothand for `field ('message', 'message text')`.
129+ // This is a shothand for `add ('message', 'message text')`.
124130pub fn (r Record) message (s string ) Record {
125- return r.field ('message' , s)
131+ return r.add ('message' , s)
126132}
127133
128134// error adds an error as new field to a record and returns the modified record.
@@ -351,6 +357,9 @@ pub struct JSONHandler {
351357pub fn (mut h JSONHandler) handle (rec Record) ! {
352358 str := json.encode[map [string ]Value](rec.fields.as_map ()) + '\n '
353359 h.writer.write (str.bytes ())!
360+ if h.writer is os.File {
361+ h.writer.flush ()
362+ }
354363}
355364
356365pub struct TextHandler {
@@ -411,7 +420,7 @@ pub fn (mut h TextHandler) handle(rec Record) ! {
411420 buf.write_byte (` ` )
412421 buf.write_string (quote (v.str ()))
413422 if j != field.value.len {
414- buf.write_byte ( ` ` )
423+ buf.write_string ( ', ' )
415424 }
416425 }
417426 } else {
@@ -422,12 +431,19 @@ pub fn (mut h TextHandler) handle(rec Record) ! {
422431 }
423432 }
424433 }
425- if i != rec.fields.len {
426- buf.write_byte (` ` )
434+ if i + 1 != rec.fields.len {
435+ if i in [0 , 1 ] {
436+ buf.write_byte (` ` )
437+ } else {
438+ buf.write_string (', ' )
439+ }
427440 }
428441 }
429442 buf.write_byte (`\n ` )
430443 h.writer.write (buf)!
444+ if h.writer is os.File {
445+ h.writer.flush ()
446+ }
431447}
432448
433449@[inline]
@@ -440,3 +456,78 @@ fn quote(input string) string {
440456 }
441457 return "'" + input + "'"
442458}
459+
460+ // struct_adapter generates the log fields list form a flat struct.
461+ // Supported struct field attrubutes:
462+ //
463+ // | Attribute | Meaning |
464+ // | ------------------- | ------------------------------------------ |
465+ // | `@[skip]` | Do not process field at all |
466+ // | `@[structlog: '-']` | Do not process field at all |
467+ // | `@[omitempty]` | Do not process field if it has empty value |
468+ //
469+ // Note: Nested struct fields are not supported.
470+ pub fn struct_adapter [T](s T) []Field {
471+ $if T ! is $struct {
472+ $compile_error ('structlog.struct_adapted: only struct types is accepted' )
473+ }
474+ mut fields := []Field{}
475+ mut skip := false
476+ mut omitempty := false
477+ $for f in s.fields {
478+ skip = false
479+ for attr in f.attrs {
480+ if attr == 'skip' || (attr.starts_with ('structlog: ' )
481+ && attr.all_after ('structlog: ' ).trim ('"\' ' ) == '-' ) {
482+ skip = true
483+ }
484+ if attr == 'omitempty' {
485+ omitempty = true
486+ }
487+ }
488+ value := s.$(f.name)
489+ if omitempty {
490+ skip = check_is_empty (value) or { false }
491+ }
492+ if ! skip {
493+ fields << field (f.name, value)
494+ }
495+ }
496+ return fields
497+ }
498+
499+ fn check_is_empty [T](val T) ? bool {
500+ $if val is string {
501+ if val == '' {
502+ return false
503+ }
504+ } $else $if val is $int || val is $float {
505+ if val == 0 {
506+ return false
507+ }
508+ } $else $if val is ? string {
509+ return val ? != ''
510+ } $else $if val is ? int {
511+ return val ? != 0
512+ } $else $if val is ? f64 || val is ? f32 {
513+ return val ? != 0.0
514+ }
515+ return true
516+ }
517+
518+ // field creates new `Field` with given name and value.
519+ // Map values will be transformed to `map[string]Value`.
520+ pub fn field [T](name string , value T) Field {
521+ $if value is $struct {
522+ $compile_error ('structlog.field: cannot pass struct as field value' )
523+ }
524+ $if value is $map {
525+ mut value_map := map [string ]Value{}
526+ for k, v in value {
527+ value_map[k.str ()] = Value (v)
528+ }
529+ return Field{name, value_map}
530+ } $else {
531+ return Field{name, value}
532+ }
533+ }
0 commit comments