github.com/cloudwego/hertz@v0.9.3/pkg/common/tracer/traceinfo/httpstats.go (about)

     1  /*
     2   * Copyright 2022 CloudWeGo Authors
     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 traceinfo
    18  
    19  import (
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/cloudwego/hertz/pkg/common/tracer/stats"
    24  )
    25  
    26  var _ HTTPStats = (*httpStats)(nil)
    27  
    28  var (
    29  	eventPool   sync.Pool
    30  	once        sync.Once
    31  	maxEventNum int
    32  )
    33  
    34  type event struct {
    35  	event  stats.Event
    36  	status stats.Status
    37  	info   string
    38  	time   time.Time
    39  }
    40  
    41  // Event implements the Event interface.
    42  func (e *event) Event() stats.Event {
    43  	return e.event
    44  }
    45  
    46  // Status implements the Event interface.
    47  func (e *event) Status() stats.Status {
    48  	return e.status
    49  }
    50  
    51  // Info implements the Event interface.
    52  func (e *event) Info() string {
    53  	return e.info
    54  }
    55  
    56  // Time implements the Event interface.
    57  func (e *event) Time() time.Time {
    58  	return e.time
    59  }
    60  
    61  // IsNil implements the Event interface.
    62  func (e *event) IsNil() bool {
    63  	return e == nil
    64  }
    65  
    66  func newEvent() interface{} {
    67  	return &event{}
    68  }
    69  
    70  func (e *event) zero() {
    71  	e.event = nil
    72  	e.status = 0
    73  	e.info = ""
    74  	e.time = time.Time{}
    75  }
    76  
    77  // Recycle reuses the event.
    78  func (e *event) Recycle() {
    79  	e.zero()
    80  	eventPool.Put(e)
    81  }
    82  
    83  type httpStats struct {
    84  	sync.RWMutex
    85  	level stats.Level
    86  
    87  	eventMap []Event
    88  
    89  	sendSize int
    90  	recvSize int
    91  
    92  	err      error
    93  	panicErr interface{}
    94  }
    95  
    96  func init() {
    97  	eventPool.New = newEvent
    98  }
    99  
   100  // Record implements the HTTPStats interface.
   101  func (h *httpStats) Record(e stats.Event, status stats.Status, info string) {
   102  	if e.Level() > h.level {
   103  		return
   104  	}
   105  	eve := eventPool.Get().(*event)
   106  	eve.event = e
   107  	eve.status = status
   108  	eve.info = info
   109  	eve.time = time.Now()
   110  
   111  	idx := e.Index()
   112  	h.Lock()
   113  	h.eventMap[idx] = eve
   114  	h.Unlock()
   115  }
   116  
   117  // SendSize implements the HTTPStats interface.
   118  func (h *httpStats) SendSize() int {
   119  	return h.sendSize
   120  }
   121  
   122  // RecvSize implements the HTTPStats interface.
   123  func (h *httpStats) RecvSize() int {
   124  	return h.recvSize
   125  }
   126  
   127  // Error implements the HTTPStats interface.
   128  func (h *httpStats) Error() error {
   129  	return h.err
   130  }
   131  
   132  // Panicked implements the HTTPStats interface.
   133  func (h *httpStats) Panicked() (bool, interface{}) {
   134  	return h.panicErr != nil, h.panicErr
   135  }
   136  
   137  // GetEvent implements the HTTPStats interface.
   138  func (h *httpStats) GetEvent(e stats.Event) Event {
   139  	idx := e.Index()
   140  	h.RLock()
   141  	evt := h.eventMap[idx]
   142  	h.RUnlock()
   143  	if evt == nil || evt.IsNil() {
   144  		return nil
   145  	}
   146  	return evt
   147  }
   148  
   149  // Level implements the HTTPStats interface.
   150  func (h *httpStats) Level() stats.Level {
   151  	return h.level
   152  }
   153  
   154  // SetSendSize sets send size.
   155  func (h *httpStats) SetSendSize(size int) {
   156  	h.sendSize = size
   157  }
   158  
   159  // SetRecvSize sets recv size.
   160  func (h *httpStats) SetRecvSize(size int) {
   161  	h.recvSize = size
   162  }
   163  
   164  // SetError sets error.
   165  func (h *httpStats) SetError(err error) {
   166  	h.err = err
   167  }
   168  
   169  // SetPanicked sets if panicked.
   170  func (h *httpStats) SetPanicked(x interface{}) {
   171  	h.panicErr = x
   172  }
   173  
   174  // SetLevel sets the level.
   175  func (h *httpStats) SetLevel(level stats.Level) {
   176  	h.level = level
   177  }
   178  
   179  // Reset resets the stats.
   180  func (h *httpStats) Reset() {
   181  	h.err = nil
   182  	h.panicErr = nil
   183  	h.recvSize = 0
   184  	h.sendSize = 0
   185  	for i := range h.eventMap {
   186  		if h.eventMap[i] != nil {
   187  			h.eventMap[i].(*event).Recycle()
   188  			h.eventMap[i] = nil
   189  		}
   190  	}
   191  }
   192  
   193  // ImmutableView restricts the httpStats into a read-only traceinfo.HTTPStats.
   194  func (h *httpStats) ImmutableView() HTTPStats {
   195  	return h
   196  }
   197  
   198  // NewHTTPStats creates a new HTTPStats.
   199  func NewHTTPStats() HTTPStats {
   200  	once.Do(func() {
   201  		stats.FinishInitialization()
   202  		maxEventNum = stats.MaxEventNum()
   203  	})
   204  	return &httpStats{
   205  		eventMap: make([]Event, maxEventNum),
   206  	}
   207  }