github.com/minio/console@v1.4.1/pkg/logger/targets.go (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2022 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package logger
    18  
    19  import (
    20  	"sync"
    21  	"sync/atomic"
    22  
    23  	"github.com/minio/console/pkg/logger/target/http"
    24  	"github.com/minio/console/pkg/logger/target/types"
    25  )
    26  
    27  // Target is the entity that we will receive
    28  // a single log entry and Send it to the log target
    29  // e.g. Send the log to a http server
    30  type Target interface {
    31  	String() string
    32  	Endpoint() string
    33  	Init() error
    34  	Cancel()
    35  	Send(entry interface{}, errKind string) error
    36  	Type() types.TargetType
    37  }
    38  
    39  var (
    40  	// swapMu must be held while reading slice info or swapping targets or auditTargets.
    41  	swapMu sync.Mutex
    42  
    43  	// systemTargets is the set of enabled loggers.
    44  	// Must be immutable at all times.
    45  	// Can be swapped to another while holding swapMu
    46  	systemTargets = []Target{}
    47  
    48  	// This is always set represent /dev/console target
    49  	consoleTgt Target
    50  
    51  	nTargets int32 // atomic count of len(targets)
    52  )
    53  
    54  // SystemTargets returns active targets.
    55  // Returned slice may not be modified in any way.
    56  func SystemTargets() []Target {
    57  	if atomic.LoadInt32(&nTargets) == 0 {
    58  		// Lock free if none...
    59  		return nil
    60  	}
    61  	swapMu.Lock()
    62  	res := systemTargets
    63  	swapMu.Unlock()
    64  	return res
    65  }
    66  
    67  // AuditTargets returns active audit targets.
    68  // Returned slice may not be modified in any way.
    69  func AuditTargets() []Target {
    70  	if atomic.LoadInt32(&nAuditTargets) == 0 {
    71  		// Lock free if none...
    72  		return nil
    73  	}
    74  	swapMu.Lock()
    75  	res := auditTargets
    76  	swapMu.Unlock()
    77  	return res
    78  }
    79  
    80  // auditTargets is the list of enabled audit loggers
    81  // Must be immutable at all times.
    82  // Can be swapped to another while holding swapMu
    83  var (
    84  	auditTargets  = []Target{}
    85  	nAuditTargets int32 // atomic count of len(auditTargets)
    86  )
    87  
    88  func cancelAllSystemTargets() {
    89  	for _, tgt := range systemTargets {
    90  		tgt.Cancel()
    91  	}
    92  }
    93  
    94  func initSystemTargets(cfgMap map[string]http.Config) (tgts []Target, err error) {
    95  	for _, l := range cfgMap {
    96  		if l.Enabled {
    97  			t := http.New(l)
    98  			if err = t.Init(); err != nil {
    99  				return tgts, err
   100  			}
   101  			tgts = append(tgts, t)
   102  		}
   103  	}
   104  	return tgts, err
   105  }
   106  
   107  // UpdateSystemTargets swaps targets with newly loaded ones from the cfg
   108  func UpdateSystemTargets(cfg Config) error {
   109  	updated, err := initSystemTargets(cfg.HTTP)
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	swapMu.Lock()
   115  	for _, tgt := range systemTargets {
   116  		// Preserve console target when dynamically updating
   117  		// other HTTP targets, console target is always present.
   118  		if tgt.Type() == types.TargetConsole {
   119  			updated = append(updated, tgt)
   120  			break
   121  		}
   122  	}
   123  	atomic.StoreInt32(&nTargets, int32(len(updated)))
   124  	cancelAllSystemTargets() // cancel running targets
   125  	systemTargets = updated
   126  	swapMu.Unlock()
   127  	return nil
   128  }
   129  
   130  func cancelAuditTargetType(t types.TargetType) {
   131  	for _, tgt := range auditTargets {
   132  		if tgt.Type() == t {
   133  			tgt.Cancel()
   134  		}
   135  	}
   136  }
   137  
   138  // UpdateAuditWebhookTargets swaps audit webhook targets with newly loaded ones from the cfg
   139  func UpdateAuditWebhookTargets(cfg Config) error {
   140  	updated, err := initSystemTargets(cfg.AuditWebhook)
   141  	if err != nil {
   142  		return err
   143  	}
   144  
   145  	swapMu.Lock()
   146  	atomic.StoreInt32(&nAuditTargets, int32(len(updated)))
   147  	cancelAuditTargetType(types.TargetHTTP) // cancel running targets
   148  	auditTargets = updated
   149  	swapMu.Unlock()
   150  	return nil
   151  }