github.com/ethersphere/bee/v2@v2.2.0/pkg/api/logger.go (about)

     1  // Copyright 2022 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package api
     6  
     7  import (
     8  	"encoding/base64"
     9  	"fmt"
    10  	"net/http"
    11  	"regexp"
    12  	"strings"
    13  
    14  	"github.com/ethersphere/bee/v2/pkg/jsonhttp"
    15  	"github.com/ethersphere/bee/v2/pkg/log"
    16  	"github.com/gorilla/mux"
    17  )
    18  
    19  // The following variables exist only to be mocked in tests.
    20  var (
    21  	logRegistryIterate   = log.RegistryIterate
    22  	logSetVerbosityByExp = log.SetVerbosityByExp
    23  )
    24  
    25  type (
    26  	data struct {
    27  		Next  node     `json:"/,omitempty"`
    28  		Names []string `json:"+,omitempty"`
    29  	}
    30  
    31  	node map[string]*data
    32  
    33  	loggerInfo struct {
    34  		Logger    string `json:"logger"`
    35  		Verbosity string `json:"verbosity"`
    36  		Subsystem string `json:"subsystem"`
    37  		ID        string `json:"id"`
    38  	}
    39  
    40  	loggerResult struct {
    41  		Tree    node         `json:"tree"`
    42  		Loggers []loggerInfo `json:"loggers"`
    43  	}
    44  )
    45  
    46  // loggerGetHandler returns all available loggers that match the specified expression.
    47  func (s *Service) loggerGetHandler(w http.ResponseWriter, r *http.Request) {
    48  	logger := s.logger.WithName("get_loggers").Build()
    49  
    50  	paths := struct {
    51  		Exp string `map:"exp,decBase64url"`
    52  	}{}
    53  	if response := s.mapStructure(mux.Vars(r), &paths); response != nil {
    54  		response("invalid path params", logger, w)
    55  		return
    56  	}
    57  
    58  	rex, err := regexp.Compile(paths.Exp)
    59  
    60  	result := loggerResult{Tree: make(node)}
    61  	logRegistryIterate(func(id, name string, verbosity log.Level, v uint) bool {
    62  		if paths.Exp == id || (rex != nil && rex.MatchString(id)) {
    63  			if int(verbosity) == int(v) {
    64  				verbosity = log.VerbosityAll
    65  			}
    66  
    67  			// Tree structure.
    68  			curr := result.Tree
    69  			path := strings.Split(name, "/")
    70  			last := len(path) - 1
    71  			for i, n := range path {
    72  				if curr[n] == nil {
    73  					curr[n] = &data{Next: make(node)}
    74  				}
    75  				if i == last {
    76  					name := fmt.Sprintf("%s|%s", verbosity, id)
    77  					curr[n].Names = append(curr[n].Names, name)
    78  				}
    79  				curr = curr[n].Next
    80  			}
    81  
    82  			// Flat structure.
    83  			result.Loggers = append(result.Loggers, loggerInfo{
    84  				Logger:    name,
    85  				Verbosity: verbosity.String(),
    86  				Subsystem: id,
    87  				ID:        base64.URLEncoding.EncodeToString([]byte(id)),
    88  			})
    89  		}
    90  		return true
    91  	})
    92  
    93  	if len(result.Loggers) == 0 && err != nil {
    94  		logger.Debug("invalid path params", "error", err)
    95  		logger.Error(nil, "invalid path params")
    96  		jsonhttp.BadRequest(w, jsonhttp.StatusResponse{
    97  			Message: "invalid path params",
    98  			Code:    http.StatusBadRequest,
    99  			Reasons: []jsonhttp.Reason{{
   100  				Field: "exp",
   101  				Error: err.Error(),
   102  			}},
   103  		})
   104  	} else {
   105  		jsonhttp.OK(w, result)
   106  	}
   107  }
   108  
   109  // loggerSetVerbosityHandler sets logger(s) verbosity level based on
   110  // the specified expression or subsystem that matches the logger(s).
   111  func (s *Service) loggerSetVerbosityHandler(w http.ResponseWriter, r *http.Request) {
   112  	logger := s.logger.WithName("put_loggers").Build()
   113  
   114  	paths := struct {
   115  		Exp       string `map:"exp,decBase64url" validate:"required"`
   116  		Verbosity string `map:"verbosity" validate:"required,oneof=none error warning info debug all"`
   117  	}{}
   118  	if response := s.mapStructure(mux.Vars(r), &paths); response != nil {
   119  		response("invalid path params", logger, w)
   120  		return
   121  	}
   122  
   123  	if err := logSetVerbosityByExp(paths.Exp, log.MustParseVerbosityLevel(paths.Verbosity)); err != nil {
   124  		logger.Debug("invalid path params", "error", err)
   125  		logger.Error(nil, "invalid path params")
   126  		jsonhttp.BadRequest(w, jsonhttp.StatusResponse{
   127  			Message: "invalid path params",
   128  			Code:    http.StatusBadRequest,
   129  			Reasons: []jsonhttp.Reason{{
   130  				Field: "exp",
   131  				Error: err.Error(),
   132  			}},
   133  		})
   134  	} else {
   135  		jsonhttp.OK(w, nil)
   136  	}
   137  }