mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 14:32:24 -05:00 
			
		
		
		
	* feat: Initial OTEL metrics * docs: add metrics documentation * fix: metrics endpoint conditional check * feat: metrics endpoint basic auth * fix: make metrics-auth-enabled default false * fix: go fmt helpers.gen.go * fix: add metric-related env vars to envparsing.sh * fix: metrics docs * fix: metrics related stuff in envparsing.sh * fix: metrics docs * chore: metrics docs wording * fix: metrics stuff in envparsing? * bump otel versions --------- Co-authored-by: Tsuribori <user@acertaindebian> Co-authored-by: Tsuribori <none@example.org> Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
		
			
				
	
	
		
			128 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright The OpenTelemetry Authors
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package metric // import "go.opentelemetry.io/otel/sdk/metric"
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"regexp"
 | |
| 	"strings"
 | |
| 
 | |
| 	"go.opentelemetry.io/otel/internal/global"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	errMultiInst = errors.New("name replacement for multiple instruments")
 | |
| 	errEmptyView = errors.New("no criteria provided for view")
 | |
| 
 | |
| 	emptyView = func(Instrument) (Stream, bool) { return Stream{}, false }
 | |
| )
 | |
| 
 | |
| // View is an override to the default behavior of the SDK. It defines how data
 | |
| // should be collected for certain instruments. It returns true and the exact
 | |
| // Stream to use for matching Instruments. Otherwise, if the view does not
 | |
| // match, false is returned.
 | |
| type View func(Instrument) (Stream, bool)
 | |
| 
 | |
| // NewView returns a View that applies the Stream mask for all instruments that
 | |
| // match criteria. The returned View will only apply mask if all non-zero-value
 | |
| // fields of criteria match the corresponding Instrument passed to the view. If
 | |
| // no criteria are provided, all field of criteria are their zero-values, a
 | |
| // view that matches no instruments is returned. If you need to match a
 | |
| // zero-value field, create a View directly.
 | |
| //
 | |
| // The Name field of criteria supports wildcard pattern matching. The "*"
 | |
| // wildcard is recognized as matching zero or more characters, and "?" is
 | |
| // recognized as matching exactly one character. For example, a pattern of "*"
 | |
| // matches all instrument names.
 | |
| //
 | |
| // The Stream mask only applies updates for non-zero-value fields. By default,
 | |
| // the Instrument the View matches against will be use for the Name,
 | |
| // Description, and Unit of the returned Stream and no Aggregation or
 | |
| // AttributeFilter are set. All non-zero-value fields of mask are used instead
 | |
| // of the default. If you need to zero out an Stream field returned from a
 | |
| // View, create a View directly.
 | |
| func NewView(criteria Instrument, mask Stream) View {
 | |
| 	if criteria.empty() {
 | |
| 		global.Error(
 | |
| 			errEmptyView, "dropping view",
 | |
| 			"mask", mask,
 | |
| 		)
 | |
| 		return emptyView
 | |
| 	}
 | |
| 
 | |
| 	var matchFunc func(Instrument) bool
 | |
| 	if strings.ContainsAny(criteria.Name, "*?") {
 | |
| 		if mask.Name != "" {
 | |
| 			global.Error(
 | |
| 				errMultiInst, "dropping view",
 | |
| 				"criteria", criteria,
 | |
| 				"mask", mask,
 | |
| 			)
 | |
| 			return emptyView
 | |
| 		}
 | |
| 
 | |
| 		// Handle branching here in NewView instead of criteria.matches so
 | |
| 		// criteria.matches remains inlinable for the simple case.
 | |
| 		pattern := regexp.QuoteMeta(criteria.Name)
 | |
| 		pattern = "^" + pattern + "$"
 | |
| 		pattern = strings.ReplaceAll(pattern, `\?`, ".")
 | |
| 		pattern = strings.ReplaceAll(pattern, `\*`, ".*")
 | |
| 		re := regexp.MustCompile(pattern)
 | |
| 		matchFunc = func(i Instrument) bool {
 | |
| 			return re.MatchString(i.Name) &&
 | |
| 				criteria.matchesDescription(i) &&
 | |
| 				criteria.matchesKind(i) &&
 | |
| 				criteria.matchesUnit(i) &&
 | |
| 				criteria.matchesScope(i)
 | |
| 		}
 | |
| 	} else {
 | |
| 		matchFunc = criteria.matches
 | |
| 	}
 | |
| 
 | |
| 	var agg Aggregation
 | |
| 	if mask.Aggregation != nil {
 | |
| 		agg = mask.Aggregation.copy()
 | |
| 		if err := agg.err(); err != nil {
 | |
| 			global.Error(
 | |
| 				err, "not using aggregation with view",
 | |
| 				"criteria", criteria,
 | |
| 				"mask", mask,
 | |
| 			)
 | |
| 			agg = nil
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return func(i Instrument) (Stream, bool) {
 | |
| 		if matchFunc(i) {
 | |
| 			return Stream{
 | |
| 				Name:            nonZero(mask.Name, i.Name),
 | |
| 				Description:     nonZero(mask.Description, i.Description),
 | |
| 				Unit:            nonZero(mask.Unit, i.Unit),
 | |
| 				Aggregation:     agg,
 | |
| 				AttributeFilter: mask.AttributeFilter,
 | |
| 			}, true
 | |
| 		}
 | |
| 		return Stream{}, false
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // nonZero returns v if it is non-zero-valued, otherwise alt.
 | |
| func nonZero[T comparable](v, alt T) T {
 | |
| 	var zero T
 | |
| 	if v != zero {
 | |
| 		return v
 | |
| 	}
 | |
| 	return alt
 | |
| }
 |