github.com/facebookincubator/go-belt@v0.0.0-20230703220935-39cd348f1a38/tool/logger/adapter/compact_logger.go (about) 1 // Copyright 2022 Meta Platforms, Inc. and affiliates. 2 // 3 // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 // 5 // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 // 7 // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 // 9 // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 // 11 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 13 package adapter 14 15 import ( 16 "github.com/facebookincubator/go-belt" 17 "github.com/facebookincubator/go-belt/pkg/field" 18 "github.com/facebookincubator/go-belt/tool/logger/types" 19 ) 20 21 // CompactLogger is an optimized interface of an abstract 22 // generic structured logger. For the full interface see "Logger". 23 // 24 // It is easier to implement a CompactLogger and then wrap it 25 // to an adapter.GenericSugar to get a Logger, than to implement 26 // a full Logger. 27 // 28 // All methods are thread-safe. 29 type CompactLogger interface { 30 belt.Tool 31 32 // Logf logs an unstructured message. Though, of course, all 33 // contextual structured fields will also be logged. 34 // 35 // This method exists mostly for convenience, for people who 36 // has not got used to proper structured logging, yet. 37 // See `LogFields` and `Log`. If one have variables they want to 38 // log, it is better for scalable observability to log them 39 // as structured values, instead of injecting them into a 40 // non-structured string. 41 Logf(level types.Level, format string, args ...any) 42 43 // LogFields logs structured fields with a explanation message. 44 // 45 // Anything that implements field.AbstractFields might be used 46 // as a collection of fields to be logged. 47 // 48 // Examples: 49 // 50 // l.LogFields(logger.LevelDebug, "new_request", field.Fields{{Key: "user_id", Value: userID}, {Key: "group_id", Value: groupID}}) 51 // l.LogFields(logger.LevelInfo, "affected entries", field.Field{Key: "mysql_affected", Value: affectedRows}) 52 // l.LogFields(logger.LevelError, "unable to fetch user info", request) // where `request` implements field.AbstractFields 53 // 54 // Sometimes it is inconvenient to manually describe each field, 55 // and for such cases see method `Log`. 56 LogFields(level types.Level, message string, fields field.AbstractFields) 57 58 // Log extracts structured fields from provided values, joins 59 // the rest into an unstructured message and logs the result. 60 // 61 // This function provides convenience (relatively to LogFields) 62 // at cost of a bit of performance. 63 // 64 // There are few ways to extract structured fields, which are 65 // applied for each value from `values` (in descending priority order): 66 // 1. If a `value` is an `*Entry` then the Entry is used (with its fields) 67 // 2. If a `value` implements field.AbstractFields then ForEachField method 68 // is used (so it is become similar to LogFields). 69 // 3. If a `value` is a structure (or a pointer to a structure) then 70 // fields of the structure are interpreted as structured fields 71 // to be logged (see explanation below). 72 // 4. If a `value` is a map then fields a constructed out of this map. 73 // 74 // Everything that does not fit into any of the rules above is just 75 // joined into an unstructured message (and works the same way 76 // as `message` in LogFields). 77 // 78 // How structures are parsed: 79 // Structures are parsed recursively. Each field name of the path in a tree 80 // of structures is added to the resulting field name (for example int "struct{A struct{B int}}" 81 // the field name will be `A.B`). 82 // To enforce another name use tag `log` (for example "struct{A int `log:"anotherName"`}"), 83 // to prevent a field from logging use tag `log:"-"`. 84 // 85 // Examples: 86 // 87 // user, err := getUser() 88 // if err != nil { 89 // l.Log(logger.LevelError, err) 90 // return err 91 // } 92 // l.Log(logger.LevelDebug, "current user", user) // fields of structure "user" will be logged 93 // l.Log(logger.LevelDebug, map[string]any{"user_id": user.ID, "group_id", user.GroupID}) 94 // l.Log(logger.LevelDebug, field.Fields{{Key: "user_id", Value: user.ID}, {Key: "group_id", Value: user.GroupID}}) 95 // l.Log(logger.LevelDebug, "current user ID is ", user.ID, " and group ID is ", user.GroupID) // will result into message "current user ID is 1234 and group ID is 5678". 96 Log(level types.Level, values ...any) 97 98 // Emitter returns the Emitter (see the description of interface "Emitter"). 99 Emitter() types.Emitter 100 101 // Level returns the current logging level (see description of "Level"). 102 Level() types.Level 103 104 // WithLevel returns a logger with logger level set to the given argument. 105 // 106 // See also the description of type "Level". 107 WithLevel(types.Level) CompactLogger 108 109 // WithPreHooks returns a Logger which includes/appends pre-hooks from the arguments. 110 // 111 // See also description of "PreHook". 112 // 113 // Special case: to reset hooks use `WithHooks()` (without any arguments). 114 WithPreHooks(...types.PreHook) CompactLogger 115 116 // WithHooks returns a Logger which includes/appends hooks from the arguments. 117 // 118 // See also description of "Hook". 119 // 120 // Special case: to reset hooks use `WithHooks()` (without any arguments). 121 WithHooks(...types.Hook) CompactLogger 122 123 // WithField returns the logger with the added field (used for structured logging). 124 WithField(key string, value any, props ...field.Property) CompactLogger 125 126 // WithFields returns the logger with the fields added (used for structured logging). 127 WithFields(fields field.AbstractFields) CompactLogger 128 129 // WithMessagePrefix adds a string to all messages logged through the derived logger 130 WithMessagePrefix(prefix string) CompactLogger 131 132 // WithEntryProperties adds props to EntryProperties of each emitted Entry. 133 // This could be used only for enabling implementation-specific behavior. 134 WithEntryProperties(props ...types.EntryProperty) CompactLogger 135 }