diff --git a/caddyhttp/httpserver/replacer.go b/caddyhttp/httpserver/replacer.go index 4286e77ef..02ad54fcb 100644 --- a/caddyhttp/httpserver/replacer.go +++ b/caddyhttp/httpserver/replacer.go @@ -286,11 +286,22 @@ func (r *replacer) getSubstitution(key string) string { return r.emptyValue } return roundDuration(time.Since(r.responseRecorder.start)).String() + case "{latency_ms}": + if r.responseRecorder == nil { + return r.emptyValue + } + elapsedDuration := time.Since(r.responseRecorder.start) + return strconv.FormatInt(convertToMilliseconds(elapsedDuration), 10) } return r.emptyValue } +//convertToMilliseconds returns the number of milliseconds in the given duration +func convertToMilliseconds(d time.Duration) int64 { + return d.Nanoseconds() / 1e6 +} + // Set sets key to value in the r.customReplacements map. func (r *replacer) Set(key, value string) { r.customReplacements["{"+key+"}"] = value diff --git a/caddyhttp/httpserver/replacer_test.go b/caddyhttp/httpserver/replacer_test.go index e64073f9f..fb5535496 100644 --- a/caddyhttp/httpserver/replacer_test.go +++ b/caddyhttp/httpserver/replacer_test.go @@ -150,3 +150,21 @@ func TestRound(t *testing.T) { } } } + +func TestMillisecondConverstion(t *testing.T) { + var testCases = map[time.Duration]int64{ + 2 * time.Second: 2000, + 9039492 * time.Nanosecond: 9, + 1000 * time.Microsecond: 1, + 127 * time.Nanosecond: 0, + 0 * time.Millisecond: 0, + 255 * time.Millisecond: 255, + } + + for dur, expected := range testCases { + numMillisecond := convertToMilliseconds(dur) + if numMillisecond != expected { + t.Errorf("Expected %v. Got %v", expected, numMillisecond) + } + } +}