github.com/facebookincubator/go-belt@v0.0.0-20230703220935-39cd348f1a38/context.go (about) 1 // Copyright 2023 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 belt 14 15 import ( 16 "context" 17 18 "github.com/facebookincubator/go-belt/internal" 19 "github.com/facebookincubator/go-belt/pkg/field" 20 ) 21 22 type ctxKeyType = internal.BeltCtxKeyType 23 24 var ctxKey = ctxKeyType{} 25 26 // CtxWithBelt returns a context derivative which includes the Belt as a value. 27 func CtxWithBelt(ctx context.Context, belt *Belt) context.Context { 28 return context.WithValue(ctx, ctxKey, belt) 29 } 30 31 // CtxBelt returns the Belt from context values. Returns the default observer if one is not set in the context. 32 func CtxBelt(ctx context.Context) *Belt { 33 observer := ctx.Value(ctxKey) 34 if observer == nil { 35 return Default() 36 } 37 return observer.(*Belt) 38 } 39 40 // WithField returns a context with a clone/derivative of the Belt which includes the passed value. 41 // 42 // The value is used by observability tooling. For example a Logger derived from the resulting 43 // Belt may add this value to the structured fields of each log entry. 44 func WithField(ctx context.Context, key string, value interface{}, props ...field.Property) context.Context { 45 return context.WithValue(ctx, ctxKey, CtxBelt(ctx).WithField(key, value, props...)) 46 } 47 48 // WithFields is the same as WithField, but adds multiple Fields at the same time. 49 // 50 // It is more performance efficient than adding fields by one. 51 func WithFields(ctx context.Context, fields field.AbstractFields) context.Context { 52 return context.WithValue(ctx, ctxKey, CtxBelt(ctx).WithFields(fields)) 53 } 54 55 // WithMap is just a sugar method, which provides logrus like way of adding fields. 56 // Effectively the same as WithFields, just the argument are in another format. 57 func WithMap(ctx context.Context, m map[string]interface{}, props ...field.Property) context.Context { 58 return context.WithValue(ctx, ctxKey, CtxBelt(ctx).WithMap(m, props...)) 59 } 60 61 // WithTool returns a context with an Belt clone/derivative, but the provided tool 62 // added to the collection of tools. 63 // 64 // Special case: to remove a specific tool, just passed an untyped nil as `tool`. 65 func WithTool(ctx context.Context, toolID ToolID, tool Tool) context.Context { 66 return context.WithValue(ctx, ctxKey, CtxBelt(ctx).WithTool(toolID, tool)) 67 } 68 69 // WithTraceID returns a context with an Belt clone/derivative with the passed traceIDs added to the set of TraceIDs. 70 func WithTraceID(ctx context.Context, traceIDs ...TraceID) context.Context { 71 return context.WithValue(ctx, ctxKey, CtxBelt(ctx).WithTraceID(traceIDs...)) 72 } 73 74 // WithArtifact returns a derivative of the context, but with the Artifact set. 75 func WithArtifact(ctx context.Context, artifactID ArtifactID, artifact Artifact) context.Context { 76 return context.WithValue(ctx, ctxKey, CtxBelt(ctx).WithArtifact(artifactID, artifact)) 77 } 78 79 // GetFields returns returns the set of fields set in the scope of this Belt. 80 // 81 // Do not modify the output of this function! It is for reading only. 82 func GetFields(ctx context.Context) field.AbstractFields { 83 return CtxBelt(ctx).Fields() 84 } 85 86 // GetArtifacts returns the collection of Artifacts in the scope of the Belt. 87 // 88 // Do not modify the output of this function! It is for reading only. 89 func GetArtifacts(ctx context.Context) Artifacts { 90 return CtxBelt(ctx).Artifacts() 91 } 92 93 // GetTraceIDs returns the current set of TraceID-s. 94 // 95 // Do not modify the output of this function! It is for reading only. 96 func GetTraceIDs(ctx context.Context) TraceIDs { 97 return CtxBelt(ctx).TraceIDs() 98 } 99 100 // GetTools returns the current collection of Tools. 101 // 102 // Do not modify the output of this function! It is for reading only. 103 func GetTools(ctx context.Context) Tools { 104 return CtxBelt(ctx).Tools() 105 } 106 107 // CtxFlush forces to flush all buffers of all the tools. 108 func Flush(ctx context.Context) { 109 CtxBelt(ctx).Flush() 110 }