github.com/phuslu/fastdns@v0.8.3-0.20240310041952-69506fc67dd1/stats.go (about)

     1  package fastdns
     2  
     3  import (
     4  	"net/netip"
     5  	"strconv"
     6  	"sync/atomic"
     7  	"time"
     8  )
     9  
    10  type Stats interface {
    11  	UpdateStats(addr netip.AddrPort, msg *Message, duration time.Duration)
    12  	AppendOpenMetrics(dst []byte) []byte
    13  }
    14  
    15  var _ Stats = (*CoreStats)(nil)
    16  
    17  type CoreStats struct {
    18  	RequestCountTotal uint64
    19  
    20  	RequestDurationSecondsBucket_0_00025 uint64
    21  	RequestDurationSecondsBucket_0_0005  uint64
    22  	RequestDurationSecondsBucket_0_001   uint64
    23  	RequestDurationSecondsBucket_0_002   uint64
    24  	RequestDurationSecondsBucket_0_004   uint64
    25  	RequestDurationSecondsBucket_0_008   uint64
    26  	RequestDurationSecondsBucket_0_016   uint64
    27  	RequestDurationSecondsBucket_0_032   uint64
    28  	RequestDurationSecondsBucket_0_064   uint64
    29  	RequestDurationSecondsBucket_0_128   uint64
    30  	RequestDurationSecondsBucket_0_256   uint64
    31  	RequestDurationSecondsBucket_0_512   uint64
    32  	RequestDurationSecondsBucket_1_024   uint64
    33  	RequestDurationSecondsBucket_2_048   uint64
    34  	RequestDurationSecondsBucket_4_096   uint64
    35  	RequestDurationSecondsBucket_8_192   uint64
    36  	RequestDurationSecondsBucket_Inf     uint64
    37  	RequestDurationSecondsSum            uint64
    38  	RequestDurationSecondsCount          uint64
    39  
    40  	RequestSizeBytesBucket_0     uint64
    41  	RequestSizeBytesBucket_100   uint64
    42  	RequestSizeBytesBucket_200   uint64
    43  	RequestSizeBytesBucket_300   uint64
    44  	RequestSizeBytesBucket_400   uint64
    45  	RequestSizeBytesBucket_511   uint64
    46  	RequestSizeBytesBucket_1023  uint64
    47  	RequestSizeBytesBucket_2047  uint64
    48  	RequestSizeBytesBucket_4095  uint64
    49  	RequestSizeBytesBucket_8291  uint64
    50  	RequestSizeBytesBucket_16000 uint64
    51  	RequestSizeBytesBucket_32000 uint64
    52  	RequestSizeBytesBucket_48000 uint64
    53  	RequestSizeBytesBucket_64000 uint64
    54  	RequestSizeBytesBucket_Inf   uint64
    55  	RequestSizeBytesSum          uint64
    56  	RequestSizeBytesCount        uint64
    57  
    58  	RequestTypeCountTotal_A     uint64
    59  	RequestTypeCountTotal_AAAA  uint64
    60  	RequestTypeCountTotal_NS    uint64
    61  	RequestTypeCountTotal_PTR   uint64
    62  	RequestTypeCountTotal_SRV   uint64
    63  	RequestTypeCountTotal_CNAME uint64
    64  	RequestTypeCountTotal_SOA   uint64
    65  	RequestTypeCountTotal_MX    uint64
    66  	RequestTypeCountTotal_TXT   uint64
    67  
    68  	ResponseRcodeCountTotal_NOERROR  uint64
    69  	ResponseRcodeCountTotal_FORMERR  uint64
    70  	ResponseRcodeCountTotal_SERVFAIL uint64
    71  	ResponseRcodeCountTotal_NOTIMP   uint64
    72  	ResponseRcodeCountTotal_NXDOMAIN uint64
    73  	ResponseRcodeCountTotal_REFUSED  uint64
    74  	ResponseRcodeCountTotal_YXDOMAIN uint64
    75  	ResponseRcodeCountTotal_XRRSET   uint64
    76  	ResponseRcodeCountTotal_NOTAUTH  uint64
    77  	ResponseRcodeCountTotal_NOTZONE  uint64
    78  
    79  	ResponseSizeBytesBucket_0     uint64
    80  	ResponseSizeBytesBucket_100   uint64
    81  	ResponseSizeBytesBucket_200   uint64
    82  	ResponseSizeBytesBucket_300   uint64
    83  	ResponseSizeBytesBucket_400   uint64
    84  	ResponseSizeBytesBucket_511   uint64
    85  	ResponseSizeBytesBucket_1023  uint64
    86  	ResponseSizeBytesBucket_2047  uint64
    87  	ResponseSizeBytesBucket_4095  uint64
    88  	ResponseSizeBytesBucket_8291  uint64
    89  	ResponseSizeBytesBucket_16000 uint64
    90  	ResponseSizeBytesBucket_32000 uint64
    91  	ResponseSizeBytesBucket_48000 uint64
    92  	ResponseSizeBytesBucket_64000 uint64
    93  	ResponseSizeBytesBucket_Inf   uint64
    94  	ResponseSizeBytesSum          uint64
    95  	ResponseSizeBytesCount        uint64
    96  
    97  	Prefix, Family, Proto, Server, Zone string
    98  }
    99  
   100  func (s *CoreStats) UpdateStats(addr netip.AddrPort, msg *Message, duration time.Duration) {
   101  	atomic.AddUint64(&s.RequestCountTotal, 1)
   102  	// request seconds
   103  	switch {
   104  	case duration <= 250*time.Microsecond:
   105  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_00025, 1)
   106  	case duration <= 500*time.Microsecond:
   107  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_0005, 1)
   108  	case duration <= 1*time.Millisecond:
   109  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_001, 1)
   110  	case duration <= 2*time.Millisecond:
   111  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_002, 1)
   112  	case duration <= 4*time.Millisecond:
   113  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_004, 1)
   114  	case duration <= 8*time.Millisecond:
   115  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_008, 1)
   116  	case duration <= 16*time.Millisecond:
   117  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_016, 1)
   118  	case duration <= 32*time.Millisecond:
   119  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_032, 1)
   120  	case duration <= 64*time.Millisecond:
   121  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_064, 1)
   122  	case duration <= 128*time.Millisecond:
   123  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_128, 1)
   124  	case duration <= 256*time.Millisecond:
   125  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_256, 1)
   126  	case duration <= 512*time.Millisecond:
   127  		atomic.AddUint64(&s.RequestDurationSecondsBucket_0_512, 1)
   128  	case duration <= 1024*time.Millisecond:
   129  		atomic.AddUint64(&s.RequestDurationSecondsBucket_1_024, 1)
   130  	case duration <= 2048*time.Millisecond:
   131  		atomic.AddUint64(&s.RequestDurationSecondsBucket_2_048, 1)
   132  	case duration <= 4096*time.Millisecond:
   133  		atomic.AddUint64(&s.RequestDurationSecondsBucket_4_096, 1)
   134  	case duration <= 8192*time.Millisecond:
   135  		atomic.AddUint64(&s.RequestDurationSecondsBucket_8_192, 1)
   136  	default:
   137  		atomic.AddUint64(&s.RequestDurationSecondsBucket_Inf, 1)
   138  	}
   139  	atomic.AddUint64(&s.RequestDurationSecondsSum, uint64(duration))
   140  	atomic.AddUint64(&s.RequestDurationSecondsCount, 1)
   141  
   142  	// request size
   143  	size := 12 + len(msg.Question.Name) + 4
   144  	switch {
   145  	case size == 0:
   146  		atomic.AddUint64(&s.RequestSizeBytesBucket_0, 1)
   147  	case size <= 100:
   148  		atomic.AddUint64(&s.RequestSizeBytesBucket_100, 1)
   149  	case size <= 200:
   150  		atomic.AddUint64(&s.RequestSizeBytesBucket_200, 1)
   151  	case size <= 300:
   152  		atomic.AddUint64(&s.RequestSizeBytesBucket_300, 1)
   153  	case size <= 400:
   154  		atomic.AddUint64(&s.RequestSizeBytesBucket_400, 1)
   155  	case size <= 511:
   156  		atomic.AddUint64(&s.RequestSizeBytesBucket_511, 1)
   157  	case size <= 1023:
   158  		atomic.AddUint64(&s.RequestSizeBytesBucket_1023, 1)
   159  	case size <= 2047:
   160  		atomic.AddUint64(&s.RequestSizeBytesBucket_2047, 1)
   161  	case size <= 4095:
   162  		atomic.AddUint64(&s.RequestSizeBytesBucket_4095, 1)
   163  	case size <= 8291:
   164  		atomic.AddUint64(&s.RequestSizeBytesBucket_8291, 1)
   165  	case size <= 16000:
   166  		atomic.AddUint64(&s.RequestSizeBytesBucket_16000, 1)
   167  	case size <= 32000:
   168  		atomic.AddUint64(&s.RequestSizeBytesBucket_32000, 1)
   169  	case size <= 48000:
   170  		atomic.AddUint64(&s.RequestSizeBytesBucket_48000, 1)
   171  	case size <= 64000:
   172  		atomic.AddUint64(&s.RequestSizeBytesBucket_64000, 1)
   173  	default:
   174  		atomic.AddUint64(&s.RequestSizeBytesBucket_Inf, 1)
   175  	}
   176  	atomic.AddUint64(&s.RequestSizeBytesSum, uint64(size))
   177  	atomic.AddUint64(&s.RequestSizeBytesCount, 1)
   178  
   179  	// request type
   180  	switch msg.Question.Type {
   181  	case TypeA:
   182  		atomic.AddUint64(&s.RequestTypeCountTotal_A, 1)
   183  	case TypeAAAA:
   184  		atomic.AddUint64(&s.RequestTypeCountTotal_AAAA, 1)
   185  	case TypeCNAME:
   186  		atomic.AddUint64(&s.RequestTypeCountTotal_CNAME, 1)
   187  	case TypeNS:
   188  		atomic.AddUint64(&s.RequestTypeCountTotal_NS, 1)
   189  	case TypeSOA:
   190  		atomic.AddUint64(&s.RequestTypeCountTotal_SOA, 1)
   191  	case TypeMX:
   192  		atomic.AddUint64(&s.RequestTypeCountTotal_MX, 1)
   193  	case TypeTXT:
   194  		atomic.AddUint64(&s.RequestTypeCountTotal_TXT, 1)
   195  	case TypePTR:
   196  		atomic.AddUint64(&s.RequestTypeCountTotal_PTR, 1)
   197  	case TypeSRV:
   198  		atomic.AddUint64(&s.RequestTypeCountTotal_SRV, 1)
   199  	}
   200  
   201  	// response rcode
   202  	switch msg.Header.Flags.Rcode() {
   203  	case RcodeNoError:
   204  		atomic.AddUint64(&s.ResponseRcodeCountTotal_NOERROR, 1)
   205  	case RcodeFormErr:
   206  		atomic.AddUint64(&s.ResponseRcodeCountTotal_FORMERR, 1)
   207  	case RcodeServFail:
   208  		atomic.AddUint64(&s.ResponseRcodeCountTotal_SERVFAIL, 1)
   209  	case RcodeNXDomain:
   210  		atomic.AddUint64(&s.ResponseRcodeCountTotal_NXDOMAIN, 1)
   211  	case RcodeNotImp:
   212  		atomic.AddUint64(&s.ResponseRcodeCountTotal_NOTIMP, 1)
   213  	case RcodeRefused:
   214  		atomic.AddUint64(&s.ResponseRcodeCountTotal_REFUSED, 1)
   215  	case RcodeYXDomain:
   216  		atomic.AddUint64(&s.ResponseRcodeCountTotal_YXDOMAIN, 1)
   217  	case RcodeNXRRSet:
   218  		atomic.AddUint64(&s.ResponseRcodeCountTotal_XRRSET, 1)
   219  	case RcodeNotAuth:
   220  		atomic.AddUint64(&s.ResponseRcodeCountTotal_NOTAUTH, 1)
   221  	case RcodeNotZone:
   222  		atomic.AddUint64(&s.ResponseRcodeCountTotal_NOTZONE, 1)
   223  	}
   224  
   225  	// response size
   226  	size = len(msg.Raw)
   227  	switch {
   228  	case size == 0:
   229  		atomic.AddUint64(&s.ResponseSizeBytesBucket_0, 1)
   230  	case size <= 100:
   231  		atomic.AddUint64(&s.ResponseSizeBytesBucket_100, 1)
   232  	case size <= 200:
   233  		atomic.AddUint64(&s.ResponseSizeBytesBucket_200, 1)
   234  	case size <= 300:
   235  		atomic.AddUint64(&s.ResponseSizeBytesBucket_300, 1)
   236  	case size <= 400:
   237  		atomic.AddUint64(&s.ResponseSizeBytesBucket_400, 1)
   238  	case size <= 511:
   239  		atomic.AddUint64(&s.ResponseSizeBytesBucket_511, 1)
   240  	case size <= 1023:
   241  		atomic.AddUint64(&s.ResponseSizeBytesBucket_1023, 1)
   242  	case size <= 2047:
   243  		atomic.AddUint64(&s.ResponseSizeBytesBucket_2047, 1)
   244  	case size <= 4095:
   245  		atomic.AddUint64(&s.ResponseSizeBytesBucket_4095, 1)
   246  	case size <= 8291:
   247  		atomic.AddUint64(&s.ResponseSizeBytesBucket_8291, 1)
   248  	case size <= 16000:
   249  		atomic.AddUint64(&s.ResponseSizeBytesBucket_16000, 1)
   250  	case size <= 32000:
   251  		atomic.AddUint64(&s.ResponseSizeBytesBucket_32000, 1)
   252  	case size <= 48000:
   253  		atomic.AddUint64(&s.ResponseSizeBytesBucket_48000, 1)
   254  	case size <= 64000:
   255  		atomic.AddUint64(&s.ResponseSizeBytesBucket_64000, 1)
   256  	default:
   257  		atomic.AddUint64(&s.ResponseSizeBytesBucket_Inf, 1)
   258  	}
   259  	atomic.AddUint64(&s.ResponseSizeBytesSum, uint64(size))
   260  	atomic.AddUint64(&s.ResponseSizeBytesCount, 1)
   261  }
   262  
   263  func (s *CoreStats) AppendOpenMetrics(dst []byte) []byte {
   264  	return s.template(dst, `
   265  {prefix}dns_request_count_total{family="{family}",proto="{proto}",server="{server}",zone="{zone}"} {request_count_total}
   266  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.00025"} {request_duration_seconds_bucket_0_00025}
   267  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.0005"} {request_duration_seconds_bucket_0_0005}
   268  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.001"} {request_duration_seconds_bucket_0_001}
   269  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.002"} {request_duration_seconds_bucket_0_002}
   270  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.004"} {request_duration_seconds_bucket_0_004}
   271  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.008"} {request_duration_seconds_bucket_0_008}
   272  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.016"} {request_duration_seconds_bucket_0_016}
   273  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.032"} {request_duration_seconds_bucket_0_032}
   274  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.064"} {request_duration_seconds_bucket_0_064}
   275  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.128"} {request_duration_seconds_bucket_0_128}
   276  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.256"} {request_duration_seconds_bucket_0_256}
   277  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="0.512"} {request_duration_seconds_bucket_0_512}
   278  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="1.024"} {request_duration_seconds_bucket_1_024}
   279  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="2.048"} {request_duration_seconds_bucket_2_048}
   280  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="4.096"} {request_duration_seconds_bucket_4_096}
   281  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="8.192"} {request_duration_seconds_bucket_8_192}
   282  {prefix}dns_request_duration_seconds_bucket{server="{server}",zone="{zone}",le="+Inf"} {request_duration_seconds_bucket_inf}
   283  {prefix}dns_request_duration_seconds_sum{server="{server}",zone="{zone}"} {request_duration_seconds_sum}
   284  {prefix}dns_request_duration_seconds_count{server="{server}",zone="{zone}"} {request_duration_seconds_count}
   285  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="0"} {request_size_bytes_bucket_0}
   286  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="100"} {request_size_bytes_bucket_100}
   287  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="200"} {request_size_bytes_bucket_200}
   288  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="300"} {request_size_bytes_bucket_300}
   289  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="400"} {request_size_bytes_bucket_400}
   290  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="511"} {request_size_bytes_bucket_511}
   291  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="1023"} {request_size_bytes_bucket_1023}
   292  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="2047"} {request_size_bytes_bucket_2047}
   293  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="4095"} {request_size_bytes_bucket_4095}
   294  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="8291"} {request_size_bytes_bucket_8291}
   295  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="16000"} {request_size_bytes_bucket_16000}
   296  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="32000"} {request_size_bytes_bucket_32000}
   297  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="48000"} {request_size_bytes_bucket_48000}
   298  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="64000"} {request_size_bytes_bucket_64000}
   299  {prefix}dns_request_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="+Inf"} {request_size_bytes_bucket_inf}
   300  {prefix}dns_request_size_bytes_sum{proto="{proto}",server="{server}",zone="{zone}"} {request_size_bytes_sum}
   301  {prefix}dns_request_size_bytes_count{proto="{proto}",server="{server}",zone="{zone}"} {request_size_bytes_count}
   302  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="A"} {request_type_count_total_a}
   303  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="AAAA"} {request_type_count_total_aaaa}
   304  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="NS"} {request_type_count_total_ns}
   305  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="PTR"} {request_type_count_total_ptr}
   306  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="SRV"} {request_type_count_total_srv}
   307  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="CNAME"} {request_type_count_total_cname}
   308  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="SOA"} {request_type_count_total_soa}
   309  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="MX"} {request_type_count_total_mx}
   310  {prefix}dns_request_type_count_total{server="{server}",zone="{zone}",type="TXT"} {request_type_count_total_txt}
   311  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="NOERROR"} {response_rcode_count_total_noerror}
   312  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="FORMERR"} {response_rcode_count_total_formerr}
   313  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="SERVFAIL"} {response_rcode_count_total_servfail}
   314  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="NXDOMAIN"} {response_rcode_count_total_nxdomain}
   315  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="NOTIMP"} {response_rcode_count_total_notimp}
   316  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="REFUSED"} {response_rcode_count_total_refused}
   317  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="YXDOMAIN"} {response_rcode_count_total_yxdomain}
   318  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="XRRSET"} {response_rcode_count_total_xrrset}
   319  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="NOTAUTH"} {response_rcode_count_total_notauth}
   320  {prefix}dns_response_rcode_count_total{server="{server}",zone="{zone}",rcode="NOTZONE"} {response_rcode_count_total_notzone}
   321  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="0"} {response_size_bytes_bucket_0}
   322  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="100"} {response_size_bytes_bucket_100}
   323  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="200"} {response_size_bytes_bucket_200}
   324  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="300"} {response_size_bytes_bucket_300}
   325  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="400"} {response_size_bytes_bucket_400}
   326  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="511"} {response_size_bytes_bucket_511}
   327  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="1023"} {response_size_bytes_bucket_1023}
   328  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="2047"} {response_size_bytes_bucket_2047}
   329  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="4095"} {response_size_bytes_bucket_4095}
   330  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="8291"} {response_size_bytes_bucket_8291}
   331  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="16000"} {response_size_bytes_bucket_16000}
   332  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="32000"} {response_size_bytes_bucket_32000}
   333  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="48000"} {response_size_bytes_bucket_48000}
   334  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="64000"} {response_size_bytes_bucket_64000}
   335  {prefix}dns_response_size_bytes_bucket{proto="{proto}",server="{server}",zone="{zone}",le="+Inf"} {response_size_bytes_bucket_inf}
   336  {prefix}dns_response_size_bytes_sum{proto="{proto}",server="{server}",zone="{zone}"} {response_size_bytes_sum}
   337  {prefix}dns_response_size_bytes_count{proto="{proto}",server="{server}",zone="{zone}"} {response_size_bytes_count}
   338  `, '{', '}')
   339  }
   340  
   341  func (s *CoreStats) template(dst []byte, template string, startTag, endTag byte) []byte {
   342  	j := 0
   343  	for i := 0; i < len(template); i++ {
   344  		switch template[i] {
   345  		case startTag:
   346  			dst = append(dst, template[j:i]...)
   347  			j = i
   348  		case endTag:
   349  			offset := 1
   350  			switch template[j+1 : i] {
   351  			case "prefix":
   352  				dst = append(dst, s.Prefix...)
   353  			case "family":
   354  				dst = append(dst, s.Family...)
   355  			case "proto":
   356  				dst = append(dst, s.Proto...)
   357  			case "server":
   358  				dst = append(dst, s.Server...)
   359  			case "zone":
   360  				dst = append(dst, s.Zone...)
   361  			case "request_count_total":
   362  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestCountTotal), 10)
   363  			case "request_duration_seconds_bucket_0_00025":
   364  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_00025), 10)
   365  			case "request_duration_seconds_bucket_0_0005":
   366  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_0005), 10)
   367  			case "request_duration_seconds_bucket_0_001":
   368  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_001), 10)
   369  			case "request_duration_seconds_bucket_0_002":
   370  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_002), 10)
   371  			case "request_duration_seconds_bucket_0_004":
   372  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_004), 10)
   373  			case "request_duration_seconds_bucket_0_008":
   374  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_008), 10)
   375  			case "request_duration_seconds_bucket_0_016":
   376  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_016), 10)
   377  			case "request_duration_seconds_bucket_0_032":
   378  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_032), 10)
   379  			case "request_duration_seconds_bucket_0_064":
   380  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_064), 10)
   381  			case "request_duration_seconds_bucket_0_128":
   382  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_128), 10)
   383  			case "request_duration_seconds_bucket_0_256":
   384  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_256), 10)
   385  			case "request_duration_seconds_bucket_0_512":
   386  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_0_512), 10)
   387  			case "request_duration_seconds_bucket_1_024":
   388  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_1_024), 10)
   389  			case "request_duration_seconds_bucket_2_048":
   390  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_2_048), 10)
   391  			case "request_duration_seconds_bucket_4_096":
   392  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_4_096), 10)
   393  			case "request_duration_seconds_bucket_8_192":
   394  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_8_192), 10)
   395  			case "request_duration_seconds_bucket_inf":
   396  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsBucket_Inf), 10)
   397  			case "request_duration_seconds_sum":
   398  				dst = strconv.AppendFloat(dst, float64(atomic.LoadUint64(&s.RequestDurationSecondsSum))/float64(time.Second), 'f', -1, 64)
   399  			case "request_duration_seconds_count":
   400  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestDurationSecondsCount), 10)
   401  			case "request_size_bytes_bucket_0":
   402  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_0), 10)
   403  			case "request_size_bytes_bucket_100":
   404  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_100), 10)
   405  			case "request_size_bytes_bucket_200":
   406  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_200), 10)
   407  			case "request_size_bytes_bucket_300":
   408  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_300), 10)
   409  			case "request_size_bytes_bucket_400":
   410  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_400), 10)
   411  			case "request_size_bytes_bucket_511":
   412  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_511), 10)
   413  			case "request_size_bytes_bucket_1023":
   414  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_1023), 10)
   415  			case "request_size_bytes_bucket_2047":
   416  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_2047), 10)
   417  			case "request_size_bytes_bucket_4095":
   418  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_4095), 10)
   419  			case "request_size_bytes_bucket_8291":
   420  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_8291), 10)
   421  			case "request_size_bytes_bucket_16000":
   422  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_16000), 10)
   423  			case "request_size_bytes_bucket_32000":
   424  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_32000), 10)
   425  			case "request_size_bytes_bucket_48000":
   426  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_48000), 10)
   427  			case "request_size_bytes_bucket_64000":
   428  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_64000), 10)
   429  			case "request_size_bytes_bucket_inf":
   430  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesBucket_Inf), 10)
   431  			case "request_size_bytes_sum":
   432  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesSum), 10)
   433  			case "request_size_bytes_count":
   434  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestSizeBytesCount), 10)
   435  			case "request_type_count_total_a":
   436  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_A), 10)
   437  			case "request_type_count_total_aaaa":
   438  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_AAAA), 10)
   439  			case "request_type_count_total_ns":
   440  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_NS), 10)
   441  			case "request_type_count_total_ptr":
   442  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_PTR), 10)
   443  			case "request_type_count_total_srv":
   444  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_SRV), 10)
   445  			case "request_type_count_total_cname":
   446  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_CNAME), 10)
   447  			case "request_type_count_total_soa":
   448  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_SOA), 10)
   449  			case "request_type_count_total_mx":
   450  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_MX), 10)
   451  			case "request_type_count_total_txt":
   452  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.RequestTypeCountTotal_TXT), 10)
   453  			case "response_rcode_count_total_noerror":
   454  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_NOERROR), 10)
   455  			case "response_rcode_count_total_formerr":
   456  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_FORMERR), 10)
   457  			case "response_rcode_count_total_servfail":
   458  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_SERVFAIL), 10)
   459  			case "response_rcode_count_total_nxdomain":
   460  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_NXDOMAIN), 10)
   461  			case "response_rcode_count_total_notimp":
   462  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_NOTIMP), 10)
   463  			case "response_rcode_count_total_refused":
   464  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_REFUSED), 10)
   465  			case "response_rcode_count_total_yxdomain":
   466  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_YXDOMAIN), 10)
   467  			case "response_rcode_count_total_xrrset":
   468  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_XRRSET), 10)
   469  			case "response_rcode_count_total_notauth":
   470  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_NOTAUTH), 10)
   471  			case "response_rcode_count_total_notzone":
   472  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseRcodeCountTotal_NOTZONE), 10)
   473  			case "response_size_bytes_bucket_0":
   474  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_0), 10)
   475  			case "response_size_bytes_bucket_100":
   476  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_100), 10)
   477  			case "response_size_bytes_bucket_200":
   478  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_200), 10)
   479  			case "response_size_bytes_bucket_300":
   480  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_300), 10)
   481  			case "response_size_bytes_bucket_400":
   482  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_400), 10)
   483  			case "response_size_bytes_bucket_511":
   484  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_511), 10)
   485  			case "response_size_bytes_bucket_1023":
   486  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_1023), 10)
   487  			case "response_size_bytes_bucket_2047":
   488  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_2047), 10)
   489  			case "response_size_bytes_bucket_4095":
   490  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_4095), 10)
   491  			case "response_size_bytes_bucket_8291":
   492  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_8291), 10)
   493  			case "response_size_bytes_bucket_16000":
   494  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_16000), 10)
   495  			case "response_size_bytes_bucket_32000":
   496  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_32000), 10)
   497  			case "response_size_bytes_bucket_48000":
   498  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_48000), 10)
   499  			case "response_size_bytes_bucket_64000":
   500  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_64000), 10)
   501  			case "response_size_bytes_bucket_inf":
   502  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesBucket_Inf), 10)
   503  			case "response_size_bytes_sum":
   504  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesSum), 10)
   505  			case "response_size_bytes_count":
   506  				dst = strconv.AppendUint(dst, atomic.LoadUint64(&s.ResponseSizeBytesCount), 10)
   507  			default:
   508  				dst = append(dst, template[j:i]...)
   509  				offset = 0
   510  			}
   511  			j = i + offset
   512  		}
   513  	}
   514  	dst = append(dst, template[j:]...)
   515  	return dst
   516  }