github.com/v2fly/tools@v0.100.0/internal/event/core/event.go (about)

     1  // Copyright 2019 The Go 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 core provides support for event based telemetry.
     6  package core
     7  
     8  import (
     9  	"fmt"
    10  	"time"
    11  
    12  	"github.com/v2fly/tools/internal/event/label"
    13  )
    14  
    15  // Event holds the information about an event of note that occurred.
    16  type Event struct {
    17  	at time.Time
    18  
    19  	// As events are often on the stack, storing the first few labels directly
    20  	// in the event can avoid an allocation at all for the very common cases of
    21  	// simple events.
    22  	// The length needs to be large enough to cope with the majority of events
    23  	// but no so large as to cause undue stack pressure.
    24  	// A log message with two values will use 3 labels (one for each value and
    25  	// one for the message itself).
    26  
    27  	static  [3]label.Label // inline storage for the first few labels
    28  	dynamic []label.Label  // dynamically sized storage for remaining labels
    29  }
    30  
    31  // eventLabelMap implements label.Map for a the labels of an Event.
    32  type eventLabelMap struct {
    33  	event Event
    34  }
    35  
    36  func (ev Event) At() time.Time { return ev.at }
    37  
    38  func (ev Event) Format(f fmt.State, r rune) {
    39  	if !ev.at.IsZero() {
    40  		fmt.Fprint(f, ev.at.Format("2006/01/02 15:04:05 "))
    41  	}
    42  	for index := 0; ev.Valid(index); index++ {
    43  		if l := ev.Label(index); l.Valid() {
    44  			fmt.Fprintf(f, "\n\t%v", l)
    45  		}
    46  	}
    47  }
    48  
    49  func (ev Event) Valid(index int) bool {
    50  	return index >= 0 && index < len(ev.static)+len(ev.dynamic)
    51  }
    52  
    53  func (ev Event) Label(index int) label.Label {
    54  	if index < len(ev.static) {
    55  		return ev.static[index]
    56  	}
    57  	return ev.dynamic[index-len(ev.static)]
    58  }
    59  
    60  func (ev Event) Find(key label.Key) label.Label {
    61  	for _, l := range ev.static {
    62  		if l.Key() == key {
    63  			return l
    64  		}
    65  	}
    66  	for _, l := range ev.dynamic {
    67  		if l.Key() == key {
    68  			return l
    69  		}
    70  	}
    71  	return label.Label{}
    72  }
    73  
    74  func MakeEvent(static [3]label.Label, labels []label.Label) Event {
    75  	return Event{
    76  		static:  static,
    77  		dynamic: labels,
    78  	}
    79  }
    80  
    81  // CloneEvent event returns a copy of the event with the time adjusted to at.
    82  func CloneEvent(ev Event, at time.Time) Event {
    83  	ev.at = at
    84  	return ev
    85  }