go.temporal.io/server@v1.23.0/common/headers/caller_info.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package headers 26 27 import ( 28 "context" 29 30 "google.golang.org/grpc/metadata" 31 ) 32 33 const ( 34 CallerTypeOperator = "operator" 35 CallerTypeAPI = "api" 36 CallerTypeBackground = "background" 37 CallerTypePreemptable = "preemptable" 38 39 CallerNameSystem = "system" 40 ) 41 42 var ( 43 SystemBackgroundCallerInfo = CallerInfo{ 44 CallerName: CallerNameSystem, 45 CallerType: CallerTypeBackground, 46 } 47 SystemPreemptableCallerInfo = CallerInfo{ 48 CallerName: CallerNameSystem, 49 CallerType: CallerTypePreemptable, 50 } 51 ) 52 53 type ( 54 CallerInfo struct { 55 // CallerName is the name of the caller. 56 // It can either user namespace name or 57 // the predefined CallerNameSystem. 58 CallerName string 59 60 // CallerType indicates if the call originates from 61 // user API calls or from system background operations. 62 CallerType string 63 64 // CallOrigin is the first API method name in the call chain. 65 // Currently, it is only specified when CallerType is CallerTypeAPI 66 CallOrigin string 67 } 68 ) 69 70 // NewCallerInfo creates a new CallerInfo 71 func NewCallerInfo( 72 callerName string, 73 callerType string, 74 callOrigin string, 75 ) CallerInfo { 76 return CallerInfo{ 77 CallerName: callerName, 78 CallerType: callerType, 79 CallOrigin: callOrigin, 80 } 81 } 82 83 // NewBackgroundCallerInfo creates a new CallerInfo with Background callerType 84 // and empty callOrigin. 85 // This is equivalent to NewCallerInfo(callerName, CallerTypeBackground, "") 86 func NewBackgroundCallerInfo( 87 callerName string, 88 ) CallerInfo { 89 return CallerInfo{ 90 CallerName: callerName, 91 CallerType: CallerTypeBackground, 92 } 93 } 94 95 // NewPreemptableCallerInfo creates a new CallerInfo with Preemptable callerType 96 // and empty callOrigin. 97 // This is equivalent to NewCallerInfo(callerName, CallerTypePreemptable, "") 98 func NewPreemptableCallerInfo( 99 callerName string, 100 ) CallerInfo { 101 return CallerInfo{ 102 CallerName: callerName, 103 CallerType: CallerTypePreemptable, 104 } 105 } 106 107 // SetCallerInfo sets callerName, callerType and CallOrigin in the context. 108 // Existing values will be overwritten if new value is not empty. 109 // TODO: consider only set the caller info to golang context instead of grpc metadata 110 // and propagate to grpc outgoing context upon making an rpc call 111 func SetCallerInfo( 112 ctx context.Context, 113 info CallerInfo, 114 ) context.Context { 115 return setIncomingMD(ctx, map[string]string{ 116 callerNameHeaderName: info.CallerName, 117 CallerTypeHeaderName: info.CallerType, 118 callOriginHeaderName: info.CallOrigin, 119 }) 120 } 121 122 // SetCallerName set caller name in the context. 123 // Existing caller name will be overwritten if exists and new caller name is not empty. 124 func SetCallerName( 125 ctx context.Context, 126 callerName string, 127 ) context.Context { 128 return setIncomingMD(ctx, map[string]string{callerNameHeaderName: callerName}) 129 } 130 131 // SetCallerType set caller type in the context. 132 // Existing caller type will be overwritten if exists and new caller type is not empty. 133 func SetCallerType( 134 ctx context.Context, 135 callerType string, 136 ) context.Context { 137 return setIncomingMD(ctx, map[string]string{CallerTypeHeaderName: callerType}) 138 } 139 140 // SetOrigin set call origin in the context. 141 // Existing call origin will be overwritten if exists and new call origin is not empty. 142 func SetOrigin( 143 ctx context.Context, 144 callOrigin string, 145 ) context.Context { 146 return setIncomingMD(ctx, map[string]string{callOriginHeaderName: callOrigin}) 147 } 148 149 func setIncomingMD( 150 ctx context.Context, 151 kv map[string]string, 152 ) context.Context { 153 mdIncoming, ok := metadata.FromIncomingContext(ctx) 154 if !ok { 155 mdIncoming = metadata.MD{} 156 } 157 158 for k, v := range kv { 159 if v != "" { 160 mdIncoming.Set(k, v) 161 } 162 } 163 164 return metadata.NewIncomingContext(ctx, mdIncoming) 165 } 166 167 // GetCallerInfo retrieves caller information from the context if exists. Empty value is returned 168 // if any piece of caller information is not specified in the context. 169 func GetCallerInfo( 170 ctx context.Context, 171 ) CallerInfo { 172 values := GetValues(ctx, callerNameHeaderName, CallerTypeHeaderName, callOriginHeaderName) 173 return CallerInfo{ 174 CallerName: values[0], 175 CallerType: values[1], 176 CallOrigin: values[2], 177 } 178 }