This file is indexed.

/usr/share/gocode/src/github.com/influxdata/influxdb/stress/v2/statement/report.go is in golang-github-influxdb-influxdb-dev 1.1.1+dfsg1-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package statement

import (
	"encoding/json"
	"fmt"
	"log"
	"math"
	"sort"
	"time"

	influx "github.com/influxdata/influxdb/client/v2"
)

// TODO: Refactor this file to utilize a common interface
// This will make adding new reports easier in the future

// Runs performance numbers for insert statements
type insertReport struct {
	name               string
	numRetries         int
	pointsPerSecond    int
	successfulWrites   int
	avgRequestBytes    int
	avgResponseTime    time.Duration
	stdDevResponseTime time.Duration
	percentile         time.Duration

	columns []string
	values  [][]interface{}
}

// Returns the version of the report that is output to STDOUT
func (ir *insertReport) String() string {
	tmplString := `Write Statement:                    %v
  Points/Sec:                          %v
  Resp Time Average:                   %v
  Resp Time Standard Deviation:        %v
  95th Percentile Write Response:      %v
  Average Request Bytes:               %v
  Successful Write Reqs:               %v
  Retries:                             %v`

	return fmt.Sprintf(tmplString,
		ir.name,
		ir.pointsPerSecond,
		ir.avgResponseTime,
		ir.stdDevResponseTime,
		ir.percentile,
		ir.avgRequestBytes,
		ir.successfulWrites,
		ir.numRetries)
}

// Returns a point representation of the report to be written to the ResultsDB
func (ir *insertReport) Point() *influx.Point {
	measurement := "testDefault"
	tags := map[string]string{}
	fields := map[string]interface{}{"field": "blank"}
	point, err := influx.NewPoint(measurement, tags, fields, time.Now())
	if err != nil {
		log.Fatalf("Error creating insertReport point\n  measurement: %v\n  tags: %v\n  fields: %v\n  error: %v\n", measurement, tags, fields, err)
	}
	return point
}

// Runs performance numbers for query statements
type queryReport struct {
	name                string
	successfulReads     int
	responseBytes       int
	stddevResponseBytes int
	avgResponseTime     time.Duration
	stdDevResponseTime  time.Duration
	percentile          time.Duration

	columns []string
	values  [][]interface{}
}

// Returns the version of the report that is output to STDOUT
func (qr *queryReport) String() string {
	tmplString := `Query Statement:                    %v
  Resp Time Average:                   %v
  Resp Time Standard Deviation:        %v
  95th Percentile Read Response:       %v
  Query Resp Bytes Average:            %v bytes
  Successful Queries:                  %v`

	return fmt.Sprintf(tmplString,
		qr.name,
		qr.avgResponseTime,
		qr.stdDevResponseTime,
		qr.percentile,
		qr.responseBytes,
		qr.successfulReads)
}

// Returns a point representation of the report to be written to the ResultsDB
func (qr *queryReport) Point() *influx.Point {
	measurement := "testDefault"
	tags := map[string]string{}
	fields := map[string]interface{}{"field": "blank"}
	point, err := influx.NewPoint(measurement, tags, fields, time.Now())
	if err != nil {
		log.Fatalf("Error creating queryReport point\n  measurement: %v\n  tags: %v\n  fields: %v\n  error: %v\n", measurement, tags, fields, err)
	}
	return point
}

// Runs performance numbers for InfluxQL statements
type influxQlReport struct {
	statement    string
	responseTime time.Duration
	success      bool

	columns []string
	values  [][]interface{}
}

// Returns the version of the report that is output to STDOUT
func (iqlr *influxQlReport) String() string {
	// Fancy format success
	var success string
	switch iqlr.success {
	case true:
		success = "[√]"
	case false:
		success = "[X]"
	}
	return fmt.Sprintf("%v '%v' -> %v", success, iqlr.statement, iqlr.responseTime)
}

// Returns a point representation of the report to be written to the ResultsDB
func (iqlr *influxQlReport) Point() *influx.Point {
	measurement := "testDefault"
	tags := map[string]string{}
	fields := map[string]interface{}{"field": "blank"}
	point, err := influx.NewPoint(measurement, tags, fields, time.Now())
	if err != nil {
		log.Fatalf("Error creating influxQL point\n  measurement: %v\n  tags: %v\n  fields: %v\n  error: %v\n", measurement, tags, fields, err)
	}
	return point
}

// Given a field or tag name this function returns the index where the values are found
func getColumnIndex(col string, columns []string) int {
	index := -1
	for i, column := range columns {
		if column == col {
			index = i
		}
	}
	return index
}

// Given a full set of results pulls the average num_bytes
func numberBytes(columns []string, values [][]interface{}) int {
	out := 0
	index := getColumnIndex("num_bytes", columns)
	for _, val := range values {
		reqBytes, err := val[index].(json.Number).Int64()
		if err != nil {
			log.Fatalf("Error coercing json.Number to Int64\n  json.Number:%v\n  error: %v\n", val[index], err)
		}
		out += int(reqBytes)
	}
	return out / len(values)
}

// Counts the number of 200(query) or 204(write) responses and returns them
func countSuccesses(columns []string, values [][]interface{}) (out int) {
	index := getColumnIndex("status_code", columns)
	for _, val := range values {
		status, err := val[index].(json.Number).Int64()
		if err != nil {
			log.Fatalf("Error coercing json.Number to Int64\n  json.Number:%v\n  error: %v\n", val[index], err)
		}
		if status == 204 || status == 200 {
			out++
		}
	}
	return out
}

// Counts number of 500 status codes
func countRetries(columns []string, values [][]interface{}) (out int) {
	index := getColumnIndex("status_code", columns)
	for _, val := range values {
		status, err := val[index].(json.Number).Int64()
		if err != nil {
			log.Fatalf("Error coercing json.Number to Int64\n  json.Number:%v\n  error: %v\n", val[index], err)
		}
		if status == 500 {
			out++
		}
	}
	return out
}

// Pulls out the response_time_ns values and formats them into ResponseTimes for reporting
func responseTimes(columns []string, values [][]interface{}) (rs ResponseTimes) {
	rs = make([]ResponseTime, 0)
	index := getColumnIndex("response_time_ns", columns)
	for _, val := range values {
		respTime, err := val[index].(json.Number).Int64()
		if err != nil {
			log.Fatalf("Error coercing json.Number to Int64\n  json.Number:%v\n  error: %v\n", val[index], err)
		}
		rs = append(rs, NewResponseTime(int(respTime)))
	}
	return rs
}

// Returns the 95th perecntile response time
func percentile(rs ResponseTimes) time.Duration {
	sort.Sort(rs)
	return time.Duration(rs[(len(rs) * 19 / 20)].Value)
}

// Returns the average response time
func avgDuration(rs ResponseTimes) (out time.Duration) {
	for _, t := range rs {
		out += time.Duration(t.Value)
	}
	return out / time.Duration(len(rs))
}

// Returns the standard deviation of a sample of response times
func stddevDuration(rs ResponseTimes) (out time.Duration) {
	avg := avgDuration(rs)

	for _, t := range rs {
		out += (avg - time.Duration(t.Value)) * (avg - time.Duration(t.Value))
	}

	return time.Duration(int64(math.Sqrt(float64(out) / float64(len(rs)))))
}