storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/logger/reqinfo.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package logger
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"sync"
    23  )
    24  
    25  // Key used for Get/SetReqInfo
    26  type contextKeyType string
    27  
    28  const contextLogKey = contextKeyType("miniolog")
    29  
    30  // KeyVal - appended to ReqInfo.Tags
    31  type KeyVal struct {
    32  	Key string
    33  	Val interface{}
    34  }
    35  
    36  // ReqInfo stores the request info.
    37  type ReqInfo struct {
    38  	RemoteHost   string   // Client Host/IP
    39  	Host         string   // Node Host/IP
    40  	UserAgent    string   // User Agent
    41  	DeploymentID string   // x-minio-deployment-id
    42  	RequestID    string   // x-amz-request-id
    43  	API          string   // API name - GetObject PutObject NewMultipartUpload etc.
    44  	BucketName   string   // Bucket name
    45  	ObjectName   string   // Object name
    46  	AccessKey    string   // Access Key
    47  	AccessGrant  string   // Access Grant
    48  	tags         []KeyVal // Any additional info not accommodated by above fields
    49  	sync.RWMutex
    50  }
    51  
    52  // NewReqInfo :
    53  func NewReqInfo(remoteHost, userAgent, deploymentID, requestID, api, bucket, object string) *ReqInfo {
    54  	req := ReqInfo{}
    55  	req.RemoteHost = remoteHost
    56  	req.UserAgent = userAgent
    57  	req.API = api
    58  	req.DeploymentID = deploymentID
    59  	req.RequestID = requestID
    60  	req.BucketName = bucket
    61  	req.ObjectName = object
    62  	return &req
    63  }
    64  
    65  // AppendTags - appends key/val to ReqInfo.tags
    66  func (r *ReqInfo) AppendTags(key string, val interface{}) *ReqInfo {
    67  	if r == nil {
    68  		return nil
    69  	}
    70  	r.Lock()
    71  	defer r.Unlock()
    72  	r.tags = append(r.tags, KeyVal{key, val})
    73  	return r
    74  }
    75  
    76  // SetTags - sets key/val to ReqInfo.tags
    77  func (r *ReqInfo) SetTags(key string, val interface{}) *ReqInfo {
    78  	if r == nil {
    79  		return nil
    80  	}
    81  	r.Lock()
    82  	defer r.Unlock()
    83  	// Search of tag key already exists in tags
    84  	var updated bool
    85  	for _, tag := range r.tags {
    86  		if tag.Key == key {
    87  			tag.Val = val
    88  			updated = true
    89  			break
    90  		}
    91  	}
    92  	if !updated {
    93  		// Append to the end of tags list
    94  		r.tags = append(r.tags, KeyVal{key, val})
    95  	}
    96  	return r
    97  }
    98  
    99  // GetTags - returns the user defined tags
   100  func (r *ReqInfo) GetTags() []KeyVal {
   101  	if r == nil {
   102  		return nil
   103  	}
   104  	r.RLock()
   105  	defer r.RUnlock()
   106  	return append([]KeyVal(nil), r.tags...)
   107  }
   108  
   109  // GetTagsMap - returns the user defined tags in a map structure
   110  func (r *ReqInfo) GetTagsMap() map[string]interface{} {
   111  	if r == nil {
   112  		return nil
   113  	}
   114  	r.RLock()
   115  	defer r.RUnlock()
   116  	m := make(map[string]interface{}, len(r.tags))
   117  	for _, t := range r.tags {
   118  		m[t.Key] = t.Val
   119  	}
   120  	return m
   121  }
   122  
   123  // SetReqInfo sets ReqInfo in the context.
   124  func SetReqInfo(ctx context.Context, req *ReqInfo) context.Context {
   125  	if ctx == nil {
   126  		LogIf(context.Background(), fmt.Errorf("context is nil"))
   127  		return nil
   128  	}
   129  	return context.WithValue(ctx, contextLogKey, req)
   130  }
   131  
   132  // GetReqInfo returns ReqInfo if set.
   133  func GetReqInfo(ctx context.Context) *ReqInfo {
   134  	if ctx != nil {
   135  		r, ok := ctx.Value(contextLogKey).(*ReqInfo)
   136  		if ok {
   137  			return r
   138  		}
   139  		r = &ReqInfo{}
   140  		SetReqInfo(ctx, r)
   141  		return r
   142  	}
   143  	return nil
   144  }