0
Files
aleesa-irc-go/vendor/github.com/HdrHistogram/hdrhistogram-go/log_writer.go
2022-09-04 04:29:50 +03:00

142 lines
6.1 KiB
Go

//The log format encodes into a single file, multiple histograms with optional shared meta data.
package hdrhistogram
import (
"fmt"
"io"
"regexp"
"time"
)
const HISTOGRAM_LOG_FORMAT_VERSION = "1.3"
const MsToNsRatio float64 = 1000000.0
type HistogramLogOptions struct {
startTimeStampSec float64
endTimeStampSec float64
maxValueUnitRatio float64
}
func DefaultHistogramLogOptions() *HistogramLogOptions {
return &HistogramLogOptions{0, 0, MsToNsRatio}
}
type HistogramLogWriter struct {
baseTime int64
log io.Writer
}
// Return the current base time offset
func (lw *HistogramLogWriter) BaseTime() int64 {
return lw.baseTime
}
// Set a base time to subtract from supplied histogram start/end timestamps when
// logging based on histogram timestamps.
// baseTime is expected to be in msec since the epoch, as histogram start/end times
// are typically stamped with absolute times in msec since the epoch.
func (lw *HistogramLogWriter) SetBaseTime(baseTime int64) {
lw.baseTime = baseTime
}
func NewHistogramLogWriter(log io.Writer) *HistogramLogWriter {
return &HistogramLogWriter{baseTime: 0, log: log}
}
// Output an interval histogram, using the start/end timestamp indicated in the histogram, and the [optional] tag associated with the histogram.
// The histogram start and end timestamps are assumed to be in msec units
//
// By convention, histogram start/end time are generally stamped with absolute times in msec
// since the epoch. For logging with absolute time stamps, the base time would remain zero ( default ).
// For logging with relative time stamps (time since a start point), the base time should be set with SetBaseTime(baseTime int64)
//
// The max value in the histogram will be reported scaled down by a default maxValueUnitRatio of 1000000.0 (which is the msec : nsec ratio).
// If you need to specify a different start/end timestamp or a different maxValueUnitRatio you should use OutputIntervalHistogramWithLogOptions(histogram *Histogram, logOptions *HistogramLogOptions)
func (lw *HistogramLogWriter) OutputIntervalHistogram(histogram *Histogram) (err error) {
return lw.OutputIntervalHistogramWithLogOptions(histogram, nil)
}
// Output an interval histogram, with the given timestamp information and the [optional] tag associated with the histogram
//
// If you specify non-nil logOptions, and non-zero start timestamp, the the specified timestamp information will be used, and the start timestamp information in the actual histogram will be ignored.
// If you specify non-nil logOptions, and non-zero start timestamp, the the specified timestamp information will be used, and the end timestamp information in the actual histogram will be ignored.
// If you specify non-nil logOptions, The max value reported with the interval line will be scaled by the given maxValueUnitRatio,
// otherwise a default maxValueUnitRatio of 1,000,000 (which is the msec : nsec ratio) will be used.
//
// By convention, histogram start/end time are generally stamped with absolute times in msec
// since the epoch. For logging with absolute time stamps, the base time would remain zero ( default ).
// For logging with relative time stamps (time since a start point), the base time should be set with SetBaseTime(baseTime int64)
func (lw *HistogramLogWriter) OutputIntervalHistogramWithLogOptions(histogram *Histogram, logOptions *HistogramLogOptions) (err error) {
tag := histogram.Tag()
var match bool
tagStr := ""
if tag != "" {
match, err = regexp.MatchString(".[, \\r\\n].", tag)
if err != nil {
return
}
if match {
err = fmt.Errorf("Tag string cannot contain commas, spaces, or line breaks. Used tag: %s", tag)
return
}
tagStr = fmt.Sprintf("Tag=%s,", tag)
}
var usedStartTime float64 = float64(histogram.StartTimeMs())
var usedEndTime float64 = float64(histogram.EndTimeMs())
var maxValueUnitRatio float64 = MsToNsRatio
if logOptions != nil {
if logOptions.startTimeStampSec != 0 {
usedStartTime = logOptions.startTimeStampSec
}
if logOptions.endTimeStampSec != 0 {
usedEndTime = logOptions.endTimeStampSec
}
maxValueUnitRatio = logOptions.maxValueUnitRatio
}
startTime := usedStartTime - float64(lw.baseTime)/1000.0
endTime := usedEndTime - float64(lw.baseTime)/1000.0
maxValueAsDouble := float64(histogram.Max()) / maxValueUnitRatio
cpayload, err := histogram.Encode(V2CompressedEncodingCookieBase)
if err != nil {
return
}
_, err = lw.log.Write([]byte(fmt.Sprintf("%s%f,%f,%f,%s\n", tagStr, startTime, endTime, maxValueAsDouble, string(cpayload))))
return
}
// Log a start time in the log.
// Start time is represented as seconds since epoch with up to 3 decimal places. Line starts with the leading text '#[StartTime:'
func (lw *HistogramLogWriter) OutputStartTime(start_time_msec int64) (err error) {
secs := start_time_msec / 1000
iso_str := time.Unix(secs, start_time_msec%int64(1000)*int64(1000000000)).Format(time.RFC3339)
_, err = lw.log.Write([]byte(fmt.Sprintf("#[StartTime: %d (seconds since epoch), %s]\n", secs, iso_str)))
return
}
// Log a base time in the log.
// Base time is represented as seconds since epoch with up to 3 decimal places. Line starts with the leading text '#[BaseTime:'
func (lw *HistogramLogWriter) OutputBaseTime(base_time_msec int64) (err error) {
secs := base_time_msec / 1000
_, err = lw.log.Write([]byte(fmt.Sprintf("#[Basetime: %d (seconds since epoch)]\n", secs)))
return
}
// Log a comment to the log.
// A comment is any line that leads with '#' that is not matched by the BaseTime or StartTime formats. Comments are ignored when parsed.
func (lw *HistogramLogWriter) OutputComment(comment string) (err error) {
_, err = lw.log.Write([]byte(fmt.Sprintf("#%s\n", comment)))
return
}
// Output a legend line to the log.
// Human readable column headers. Ignored when parsed.
func (lw *HistogramLogWriter) OutputLegend() (err error) {
_, err = lw.log.Write([]byte("\"StartTimestamp\",\"Interval_Length\",\"Interval_Max\",\"Interval_Compressed_Histogram\"\n"))
return
}
// Output a log format version to the log.
func (lw *HistogramLogWriter) OutputLogFormatVersion() (err error) {
return lw.OutputComment(fmt.Sprintf("[Histogram log format version %s]", HISTOGRAM_LOG_FORMAT_VERSION))
}