diff --git a/content/quickstart/go/metrics.md b/content/quickstart/go/metrics.md
index 0c689e7e..de0dc288 100644
--- a/content/quickstart/go/metrics.md
+++ b/content/quickstart/go/metrics.md
@@ -80,7 +80,7 @@ touch repl.go
Next, put the following code inside of `repl.go`:
-{{}}
+```go
package main
import (
@@ -111,7 +111,7 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
@@ -131,7 +131,8 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(in []byte) (out []byte, err error) {
return bytes.ToUpper(in), nil
}
-{{}}
+
+```
You can run the code via `go run repl.go`.
@@ -142,8 +143,8 @@ You can run the code via `go run repl.go`.
To enable metrics, we’ll import a couple of packages:
-{{}}
-{{}}
+{{% tabs Snippet All %}}
+```go
import (
"bufio"
"bytes"
@@ -157,9 +158,9 @@ import (
"go.opencensus.io/stats"
"go.opencensus.io/tag"
)
-{{}}
+```
-{{}}
+```go
package main
import (
@@ -195,7 +196,7 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
@@ -215,29 +216,26 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(in []byte) (out []byte, err error) {
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+```
+{{% /tabs %}}
### Create Metrics
First, we will create the variables needed to later record our metrics.
-{{}}
-{{}}
+{{% tabs Snippet All %}}
+```go
var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
-{{}}
+```
-{{}}
+```go
package main
import (
@@ -258,9 +256,6 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
@@ -284,7 +279,7 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
@@ -304,21 +299,23 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(in []byte) (out []byte, err error) {
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+```
+{{% /tabs %}}
### Create Tags
Now we will create the variable later needed to add extra text meta-data to our metrics.
-{{}}
-{{}}
+{{% tabs Snippet All %}}
+```go
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
-{{}}
+```
-{{}}
+```go
package main
import (
@@ -339,15 +336,14 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
func main() {
@@ -369,7 +365,7 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
@@ -389,8 +385,8 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(in []byte) (out []byte, err error) {
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+```
+{{% /tabs %}}
We will later use this tag, called KeyMethod, to record what method is being invoked. In our scenario, we will only use it to record that "repl" is calling our data.
@@ -406,15 +402,15 @@ Now we will insert a specific tag called "repl". It will give us a new `context.
For example
```go
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
```
and for complete usage:
-{{}}
-{{}}
-func readEvaluateProcess(br *bufio.Reader) error {
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+{{% tabs Snippet All %}}
+```go
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
+ ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
if err != nil {
return err
}
@@ -432,9 +428,9 @@ func readEvaluateProcess(br *bufio.Reader) error {
fmt.Printf("< %s\n\n", out)
return nil
}
-{{}}
+```
-{{}}
+```go
package main
import (
@@ -455,15 +451,14 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
func main() {
@@ -485,8 +480,8 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
+ ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
if err != nil {
return err
}
@@ -510,21 +505,23 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(in []byte) (out []byte, err error) {
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+```
+{{% /tabs %}}
When recording metrics, we will need the `ctx` from `tag.New`. We will be recording metrics in `processLine`, so let's go ahead and make `ctx` available now.
-{{}}
-{{}}
+{{% tabs Snippet All %}}
+```go
// ...
out, err := processLine(ctx, line)
// ...
func processLine(ctx context.Context, in []byte) (out []byte, err error) {
-{{}}
+ // ...
+}
+```
-{{}}
+```go
package main
import (
@@ -545,15 +542,14 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
func main() {
@@ -575,7 +571,7 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
@@ -596,33 +592,42 @@ func processLine(ctx context.Context, in []byte) (out []byte, err error) {
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+
+```
+{{% /tabs %}}
### Recording Metrics
Now we will record the desired metrics. To do so, we will use `stats.Record` and pass in our `ctx` and [previously instantiated metrics variables](#create-metrics).
-{{}}
-{{}}
-func readEvaluateProcess(br *bufio.Reader) error {
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+{{% tabs Snippet All %}}
+```go
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
+ ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
if err != nil {
return err
}
+ defer func() {
+ if terr != nil {
+ ctx, _ = tag.New(ctx, tag.Upsert(KeyStatus, "ERROR"),
+ tag.Upsert(KeyError, terr.Error()))
+ }
+
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)))
+ }()
+
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
if err != io.EOF {
- stats.Record(ctx, MErrors.M(1))
+ return err
}
- return err
+ log.Fatal(err)
}
out, err := processLine(ctx, line)
if err != nil {
- stats.Record(ctx, MErrors.M(1))
return err
}
fmt.Printf("< %s\n\n", out)
@@ -634,15 +639,19 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(ctx context.Context, in []byte) (out []byte, err error) {
startTime := time.Now()
defer func() {
- ms := float64(time.Since(startTime).Nanoseconds()) / 1e6
- stats.Record(ctx, MLatencyMs.M(ms), MLineLengths.M(int64(len(in))))
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)),
+ MLineLengths.M(int64(len(in))))
}()
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+func sinceInMilliseconds(startTime time.Time) float64 {
+ return float64(time.Since(startTime).Nanoseconds()) / 1e6
+}
+```
+
+```go
package main
import (
@@ -663,15 +672,14 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
func main() {
@@ -693,24 +701,32 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
+ ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
if err != nil {
return err
}
+ defer func() {
+ if terr != nil {
+ ctx, _ = tag.New(ctx, tag.Upsert(KeyStatus, "ERROR"),
+ tag.Upsert(KeyError, terr.Error()))
+ }
+
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)))
+ }()
+
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
if err != io.EOF {
- stats.Record(ctx, MErrors.M(1))
+ return err
}
- return err
+ log.Fatal(err)
}
out, err := processLine(ctx, line)
if err != nil {
- stats.Record(ctx, MErrors.M(1))
return err
}
fmt.Printf("< %s\n\n", out)
@@ -722,22 +738,26 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(ctx context.Context, in []byte) (out []byte, err error) {
startTime := time.Now()
defer func() {
- ms := float64(time.Since(startTime).Nanoseconds()) / 1e6
- stats.Record(ctx, MLatencyMs.M(ms), MLineLengths.M(int64(len(in))))
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)),
+ MLineLengths.M(int64(len(in))))
}()
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+
+func sinceInMilliseconds(startTime time.Time) float64 {
+ return float64(time.Since(startTime).Nanoseconds()) / 1e6
+}
+```
+{{% /tabs %}}
## Enable Views
We will be adding the View package: `"go.opencensus.io/stats/view"`
### Import Packages
-{{}}
-{{}}
+{{% tabs Snippet All %}}
+```go
import (
"bufio"
"bytes"
@@ -752,9 +772,9 @@ import (
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
)
-{{}}
+```
-{{}}
+```go
package main
import (
@@ -776,15 +796,14 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
func main() {
@@ -806,24 +825,32 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
+ ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
if err != nil {
return err
}
+ defer func() {
+ if terr != nil {
+ ctx, _ = tag.New(ctx, tag.Upsert(KeyStatus, "ERROR"),
+ tag.Upsert(KeyError, terr.Error()))
+ }
+
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)))
+ }()
+
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
if err != io.EOF {
- stats.Record(ctx, MErrors.M(1))
+ return err
}
- return err
+ log.Fatal(err)
}
out, err := processLine(ctx, line)
if err != nil {
- stats.Record(ctx, MErrors.M(1))
return err
}
fmt.Printf("< %s\n\n", out)
@@ -835,20 +862,24 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(ctx context.Context, in []byte) (out []byte, err error) {
startTime := time.Now()
defer func() {
- ms := float64(time.Since(startTime).Nanoseconds()) / 1e6
- stats.Record(ctx, MLatencyMs.M(ms), MLineLengths.M(int64(len(in))))
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)),
+ MLineLengths.M(int64(len(in))))
}()
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+
+func sinceInMilliseconds(startTime time.Time) float64 {
+ return float64(time.Since(startTime).Nanoseconds()) / 1e6
+}
+```
+{{% /tabs %}}
### Create Views
We now determine how our metrics will be organized by creating `Views`.
-{{}}
-{{}}
+{{% tabs Snippet All %}}
+```go
var (
LatencyView = &view.View{
Name: "demo/latency",
@@ -867,13 +898,6 @@ var (
Aggregation: view.Count(),
}
- ErrorCountView = &view.View{
- Name: "demo/errors",
- Measure: MErrors,
- Description: "The number of errors encountered",
- Aggregation: view.Count(),
- }
-
LineLengthView = &view.View{
Name: "demo/line_lengths",
Description: "Groups the lengths of keys in buckets",
@@ -882,9 +906,9 @@ var (
Aggregation: view.Distribution(0, 5, 10, 15, 20, 40, 60, 80, 100, 200, 400, 600, 800, 1000),
}
)
-{{}}
+```
-{{}}
+```go
package main
import (
@@ -906,15 +930,14 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
var (
@@ -935,13 +958,6 @@ var (
Aggregation: view.Count(),
}
- ErrorCountView = &view.View{
- Name: "demo/errors",
- Measure: MErrors,
- Description: "The number of errors encountered",
- Aggregation: view.Count(),
- }
-
LineLengthView = &view.View{
Name: "demo/line_lengths",
Description: "Groups the lengths of keys in buckets",
@@ -970,24 +986,32 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
+ ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
if err != nil {
return err
}
+ defer func() {
+ if terr != nil {
+ ctx, _ = tag.New(ctx, tag.Upsert(KeyStatus, "ERROR"),
+ tag.Upsert(KeyError, terr.Error()))
+ }
+
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)))
+ }()
+
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
if err != io.EOF {
- stats.Record(ctx, MErrors.M(1))
+ return err
}
- return err
+ log.Fatal(err)
}
out, err := processLine(ctx, line)
if err != nil {
- stats.Record(ctx, MErrors.M(1))
return err
}
fmt.Printf("< %s\n\n", out)
@@ -999,20 +1023,24 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(ctx context.Context, in []byte) (out []byte, err error) {
startTime := time.Now()
defer func() {
- ms := float64(time.Since(startTime).Nanoseconds()) / 1e6
- stats.Record(ctx, MLatencyMs.M(ms), MLineLengths.M(int64(len(in))))
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)),
+ MLineLengths.M(int64(len(in))))
}()
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+
+func sinceInMilliseconds(startTime time.Time) float64 {
+ return float64(time.Since(startTime).Nanoseconds()) / 1e6
+}
+```
+{{% /tabs %}}
### Register Views
We now register the views and set the reporting period.
-{{}}
-{{}}
+{{% tabs Snippet All %}}
+```go
func main() {
// In a REPL:
// 1. Read input
@@ -1020,7 +1048,7 @@ func main() {
br := bufio.NewReader(os.Stdin)
// Register the views
- if err := view.Register(LatencyView, LineCountView, ErrorCountView, LineLengthView); err != nil {
+ if err := view.Register(LatencyView, LineCountView, LineLengthView); err != nil {
log.Fatalf("Failed to register views: %v", err)
}
@@ -1034,9 +1062,9 @@ func main() {
}
}
}
-{{}}
+```
-{{}}
+```go
package main
import (
@@ -1058,15 +1086,14 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
var (
@@ -1087,13 +1114,6 @@ var (
Aggregation: view.Count(),
}
- ErrorCountView = &view.View{
- Name: "demo/errors",
- Measure: MErrors,
- Description: "The number of errors encountered",
- Aggregation: view.Count(),
- }
-
LineLengthView = &view.View{
Name: "demo/line_lengths",
Description: "Groups the lengths of keys in buckets",
@@ -1110,7 +1130,7 @@ func main() {
br := bufio.NewReader(os.Stdin)
// Register the views
- if err := view.Register(LatencyView, LineCountView, ErrorCountView, LineLengthView); err != nil {
+ if err := view.Register(LatencyView, LineCountView, LineLengthView); err != nil {
log.Fatalf("Failed to register views: %v", err)
}
@@ -1127,24 +1147,32 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
+ ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
if err != nil {
return err
}
+ defer func() {
+ if terr != nil {
+ ctx, _ = tag.New(ctx, tag.Upsert(KeyStatus, "ERROR"),
+ tag.Upsert(KeyError, terr.Error()))
+ }
+
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)))
+ }()
+
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
if err != io.EOF {
- stats.Record(ctx, MErrors.M(1))
+ return err
}
- return err
+ log.Fatal(err)
}
out, err := processLine(ctx, line)
if err != nil {
- stats.Record(ctx, MErrors.M(1))
return err
}
fmt.Printf("< %s\n\n", out)
@@ -1156,25 +1184,28 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(ctx context.Context, in []byte) (out []byte, err error) {
startTime := time.Now()
defer func() {
- ms := float64(time.Since(startTime).Nanoseconds()) / 1e6
- stats.Record(ctx, MLatencyMs.M(ms), MLineLengths.M(int64(len(in))))
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)),
+ MLineLengths.M(int64(len(in))))
}()
return bytes.ToUpper(in), nil
}
-{{}}
-{{}}
+
+func sinceInMilliseconds(startTime time.Time) float64 {
+ return float64(time.Since(startTime).Nanoseconds()) / 1e6
+}
+```
+{{% /tabs %}}
## Exporting stats
### Register the views
```go
- // Register the views
- if err := view.Register(LatencyView, LineCountView, ErrorCountView, LineLengthView); err != nil {
- log.Fatalf("Failed to register views: %v", err)
- }
-
+// Register the views
+if err := view.Register(LatencyView, LineCountView, LineLengthView); err != nil {
+ log.Fatalf("Failed to register views: %v", err)
+}
```
@@ -1188,48 +1219,48 @@ to http endpoint "/metrics".
```go
import (
- "log"
- "net/http"
+ "log"
+ "net/http"
- "go.opencensus.io/exporter/prometheus"
- "go.opencensus.io/stats/view"
+ "go.opencensus.io/exporter/prometheus"
+ "go.opencensus.io/stats/view"
)
func main() {
- pe, err := prometheus.NewExporter(prometheus.Options{
- Namespace: "ocmetricstutorial",
- })
- if err != nil {
- log.Fatalf("Failed to create the Prometheus stats exporter: %v", err)
- }
-
- // Register the Prometheus exporters as a stats exporter.
- view.RegisterExporter(pe)
-
- // Now finally run the Prometheus exporter as a scrape endpoint.
- // We'll run the server on port 8888.
- go func() {
- mux := http.NewServeMux()
- mux.Handle("/metrics", pe)
- if err := http.ListenAndServe(":8888", mux); err != nil {
- log.Fatalf("Failed to run Prometheus scrape endpoint: %v", err)
- }
- }()
+ pe, err := prometheus.NewExporter(prometheus.Options{
+ Namespace: "ocmetricstutorial",
+ })
+ if err != nil {
+ log.Fatalf("Failed to create the Prometheus stats exporter: %v", err)
+ }
+
+ // Register the Prometheus exporters as a stats exporter.
+ view.RegisterExporter(pe)
+
+ // Now finally run the Prometheus exporter as a scrape endpoint.
+ // We'll run the server on port 8888.
+ go func() {
+ mux := http.NewServeMux()
+ mux.Handle("/metrics", pe)
+ if err := http.ListenAndServe(":8888", mux); err != nil {
+ log.Fatalf("Failed to run Prometheus scrape endpoint: %v", err)
+ }
+ }()
}
```
### Register the exporter
```go
- // Register the Prometheus exporter.
- // This step is needed so that metrics can be exported.
- view.RegisterExporter(pe)
+// Register the Prometheus exporter.
+// This step is needed so that metrics can be exported.
+view.RegisterExporter(pe)
```
## End to end code
Collectively the code will be
-{{}}
+```go
package main
import (
@@ -1253,15 +1284,14 @@ var (
// The latency in milliseconds
MLatencyMs = stats.Float64("repl/latency", "The latency in milliseconds per REPL loop", "ms")
- // Encounters the number of non EOF(end-of-file) errors.
- MErrors = stats.Int64("repl/errors", "The number of errors encountered", "1")
-
// Counts/groups the lengths of lines read in.
MLineLengths = stats.Int64("repl/line_lengths", "The distribution of line lengths", "By")
)
var (
KeyMethod, _ = tag.NewKey("method")
+ KeyStatus, _ = tag.NewKey("status")
+ KeyError, _ = tag.NewKey("error")
)
var (
@@ -1282,13 +1312,6 @@ var (
Aggregation: view.Count(),
}
- ErrorCountView = &view.View{
- Name: "demo/errors",
- Measure: MErrors,
- Description: "The number of errors encountered",
- Aggregation: view.Count(),
- }
-
LineLengthView = &view.View{
Name: "demo/line_lengths",
Description: "Groups the lengths of keys in buckets",
@@ -1301,7 +1324,7 @@ var (
func main() {
// Register the views, it is imperative that this step exists
// lest recorded metrics will be dropped and never exported.
- if err := view.Register(LatencyView, LineCountView, ErrorCountView, LineLengthView); err != nil {
+ if err := view.Register(LatencyView, LineCountView, LineLengthView); err != nil {
log.Fatalf("Failed to register the views: %v", err)
}
@@ -1332,7 +1355,7 @@ func main() {
br := bufio.NewReader(os.Stdin)
// Register the views
- if err := view.Register(LatencyView, LineCountView, ErrorCountView, LineLengthView); err != nil {
+ if err := view.Register(LatencyView, LineCountView, LineLengthView); err != nil {
log.Fatalf("Failed to register views: %v", err)
}
@@ -1349,24 +1372,32 @@ func main() {
// readEvaluateProcess reads a line from the input reader and
// then processes it. It returns an error if any was encountered.
-func readEvaluateProcess(br *bufio.Reader) error {
- ctx, err := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"))
+func readEvaluateProcess(br *bufio.Reader) (terr error) {
+ ctx, _ := tag.New(context.Background(), tag.Insert(KeyMethod, "repl"), tag.Insert(KeyStatus, "OK"))
if err != nil {
return err
}
+ defer func() {
+ if terr != nil {
+ ctx, _ = tag.New(ctx, tag.Upsert(KeyStatus, "ERROR"),
+ tag.Upsert(KeyError, terr.Error()))
+ }
+
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)))
+ }()
+
fmt.Printf("> ")
line, _, err := br.ReadLine()
if err != nil {
if err != io.EOF {
- stats.Record(ctx, MErrors.M(1))
+ return err
}
- return err
+ log.Fatal(err)
}
out, err := processLine(ctx, line)
if err != nil {
- stats.Record(ctx, MErrors.M(1))
return err
}
fmt.Printf("< %s\n\n", out)
@@ -1378,13 +1409,17 @@ func readEvaluateProcess(br *bufio.Reader) error {
func processLine(ctx context.Context, in []byte) (out []byte, err error) {
startTime := time.Now()
defer func() {
- ms := float64(time.Since(startTime).Nanoseconds()) / 1e6
- stats.Record(ctx, MLatencyMs.M(ms), MLineLengths.M(int64(len(in))))
+ stats.Record(ctx, MLatencyMs.M(sinceInMilliseconds(startTime)),
+ MLineLengths.M(int64(len(in))))
}()
return bytes.ToUpper(in), nil
}
-{{}}
+
+func sinceInMilliseconds(startTime time.Time) float64 {
+ return float64(time.Since(startTime).Nanoseconds()) / 1e6
+}
+```
### Running the tutorial
diff --git a/content/quickstart/java/metrics.md b/content/quickstart/java/metrics.md
index 7225ea8b..3ffc9c52 100644
--- a/content/quickstart/java/metrics.md
+++ b/content/quickstart/java/metrics.md
@@ -328,9 +328,6 @@ First, we will create the variables needed to later record our metrics. Place th
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
-// Counts the number of non EOF(end-of-file) errors.
-private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
@@ -368,9 +365,6 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
@@ -417,6 +411,8 @@ Insert the following snippet on the line before `private static final Tagger tag
{{}}
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+private static final TagKey KEY_STATUS = TagKey.create("status");
+private static final TagKey KEY_ERROR = TagKey.create("error");
{{}}
{{}}
@@ -445,14 +441,15 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+ // The tag "status"
+ private static final TagKey KEY_STATUS = TagKey.create("status");
+ // The tag "error"
+ private static final TagKey KEY_ERROR = TagKey.create("error");
private static final Tagger tagger = Tags.getTagger();
private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
@@ -503,7 +500,7 @@ Later, if we used `OS_Key`, we will be given an opportunity to enter values such
**Note**: `OS_Key` is not used in this quickstart. It is only used as an example in this text block.
{{% /notice %}}
-We will now create helper functions to assist us with recording Tagged Stats. One will record a `Long`, and the other will record a `Double`.
+We will now create helper functions to assist us with recording Tagged Stats. One will record a `Long`, another a `Double`, and finally an array of `Doubles`.
Insert the following snippet after `private static void recordStat`:
@@ -522,6 +519,18 @@ private static void recordTaggedStat(TagKey key, String value, MeasureDouble md,
statsRecorder.newMeasureMap().put(md, d).record();
}
}
+
+private static void recordTaggedStat(TagKey[] keys, String[] values, MeasureDouble md, Double d) {
+ TagContextBuilder builder = tagger.emptyBuilder();
+ for (int i = 0; i < keys.length; i++) {
+ builder.put(keys[i], TagValue.create(values[i]));
+ }
+ TagContext tctx = builder.build();
+
+ try (Scope ss = tagger.withTagContext(tctx)) {
+ statsRecorder.newMeasureMap().put(md, d).record();
+ }
+}
{{}}
{{}}
@@ -550,14 +559,15 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+ // The tag "status"
+ private static final TagKey KEY_STATUS = TagKey.create("status");
+ // The tag "error"
+ private static final TagKey KEY_ERROR = TagKey.create("error");
private static final Tagger tagger = Tags.getTagger();
private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
@@ -592,6 +602,18 @@ public class Repl {
}
}
+ private static void recordTaggedStat(TagKey[] keys, String[] values, MeasureDouble md, Double d) {
+ TagContextBuilder builder = tagger.emptyBuilder();
+ for (int i = 0; i < keys.length; i++) {
+ builder.put(keys[i], TagValue.create(values[i]));
+ }
+ TagContext tctx = builder.build();
+
+ try (Scope ss = tagger.withTagContext(tctx)) {
+ statsRecorder.newMeasureMap().put(md, d).record();
+ }
+ }
+
private static String processLine(String line) {
return line.toUpperCase();
}
@@ -612,18 +634,24 @@ Finally, we'll hook our stat recorders in to `main`, `processLine`, and `readEva
{{}}
{{}}
-public static void main(String ...args) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+while (true) {
+ long startTimeNs = System.nanoTime();
- while (true) {
- try {
- readEvaluateProcessLine(stdin);
- } catch (IOException e) {
- System.err.println("EOF bye "+ e);
- return;
- } catch (Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
- }
+ try {
+ readEvaluateProcessLine(stdin);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
+ } catch (IOException e) {
+ System.err.println("EOF bye "+ e);
+ return;
+ } catch (Exception e) {
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS, KEY_ERROR};
+ String[] tagValues = {"repl", "ERROR", e.getMessage()};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
+ return;
}
}
@@ -633,23 +661,25 @@ private static String processLine(String line) {
try {
return line.toUpperCase();
} finally {
- long totalTimeNs = System.nanoTime() - startTimeNs;
- double timespentMs = (new Double(totalTimeNs))/1e6;
- recordTaggedStat(KEY_METHOD, "processLine", M_LATENCY_MS, timespentMs);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS, sinceInMilliseconds(startTimeNs));
}
}
+private static double sinceInMilliseconds(long startTimeNs) {
+ return (new Double(System.nanoTime() - startTimeNs))/1e6;
+}
+
private static void readEvaluateProcessLine(BufferedReader in) throws IOException {
System.out.print("> ");
System.out.flush();
- try {
- String line = in.readLine();
- String processed = processLine(line);
- System.out.println("< " + processed + "\n");
- recordStat(M_LINE_LENGTHS, new Long(line.length()));
- } catch(Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
+ String line = in.readLine();
+ String processed = processLine(line);
+ System.out.println("< " + processed + "\n");
+ if (line != null && line.length() > 0) {
+ recordStat(M_LINE_LENGTHS, new Long(line.length()));
}
}
{{}}
@@ -680,14 +710,15 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+ // The tag "status"
+ private static final TagKey KEY_STATUS = TagKey.create("status");
+ // The tag "error"
+ private static final TagKey KEY_ERROR = TagKey.create("error");
private static final Tagger tagger = Tags.getTagger();
private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
@@ -696,13 +727,23 @@ public class Repl {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
+ long startTimeNs = System.nanoTime();
+
try {
readEvaluateProcessLine(stdin);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
} catch (IOException e) {
System.err.println("EOF bye "+ e);
return;
} catch (Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS, KEY_ERROR};
+ String[] tagValues = {"repl", "ERROR", e.getMessage()};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
+ return;
}
}
}
@@ -725,15 +766,27 @@ public class Repl {
}
}
+ private static void recordTaggedStat(TagKey[] keys, String[] values, MeasureDouble md, Double d) {
+ TagContextBuilder builder = tagger.emptyBuilder();
+ for (int i = 0; i < keys.length; i++) {
+ builder.put(keys[i], TagValue.create(values[i]));
+ }
+ TagContext tctx = builder.build();
+
+ try (Scope ss = tagger.withTagContext(tctx)) {
+ statsRecorder.newMeasureMap().put(md, d).record();
+ }
+ }
+
private static String processLine(String line) {
long startTimeNs = System.nanoTime();
try {
return line.toUpperCase();
} finally {
- long totalTimeNs = System.nanoTime() - startTimeNs;
- double timespentMs = (new Double(totalTimeNs))/1e6;
- recordTaggedStat(KEY_METHOD, "processLine", M_LATENCY_MS, timespentMs);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS, sinceInMilliseconds(startTimeNs));
}
}
@@ -741,13 +794,11 @@ public class Repl {
System.out.print("> ");
System.out.flush();
- try {
- String line = in.readLine();
- String processed = processLine(line);
- System.out.println("< " + processed + "\n");
+ String line = in.readLine();
+ String processed = processLine(line);
+ System.out.println("< " + processed + "\n");
+ if (line != null && line.length() > 0) {
recordStat(M_LINE_LENGTHS, new Long(line.length()));
- } catch(Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
}
}
}
@@ -812,14 +863,15 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+ // The tag "status"
+ private static final TagKey KEY_STATUS = TagKey.create("status");
+ // The tag "error"
+ private static final TagKey KEY_ERROR = TagKey.create("error");
private static final Tagger tagger = Tags.getTagger();
private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
@@ -854,15 +906,27 @@ public class Repl {
}
}
+ private static void recordTaggedStat(TagKey[] keys, String[] values, MeasureDouble md, Double d) {
+ TagContextBuilder builder = tagger.emptyBuilder();
+ for (int i = 0; i < keys.length; i++) {
+ builder.put(keys[i], TagValue.create(values[i]));
+ }
+ TagContext tctx = builder.build();
+
+ try (Scope ss = tagger.withTagContext(tctx)) {
+ statsRecorder.newMeasureMap().put(md, d).record();
+ }
+ }
+
private static String processLine(String line) {
long startTimeNs = System.nanoTime();
try {
return line.toUpperCase();
} finally {
- long totalTimeNs = System.nanoTime() - startTimeNs;
- double timespentMs = (new Double(totalTimeNs))/1e6;
- recordTaggedStat(KEY_METHOD, "processLine", M_LATENCY_MS, timespentMs);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS, sinceInMilliseconds(startTimeNs));
}
}
@@ -870,13 +934,11 @@ public class Repl {
System.out.print("> ");
System.out.flush();
- try {
- String line = in.readLine();
- String processed = processLine(line);
- System.out.println("< " + processed + "\n");
+ String line = in.readLine();
+ String processed = processLine(line);
+ System.out.println("< " + processed + "\n");
+ if (line != null && line.length() > 0) {
recordStat(M_LINE_LENGTHS, new Long(line.length()));
- } catch(Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
}
}
}
@@ -910,10 +972,9 @@ private static void registerAllViews() {
// Define the views
View[] views = new View[]{
- View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.singletonList(KEY_METHOD)),
- View.create(Name.create("ocjavametrics/lines_in"), "The number of lines read in from standard input", M_LINES_LENGTH, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/errors"), "The number of errors encountered", M_ERRORS, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/line_length"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
+ View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.unmodifiableList(Arrays.asList(KEY_METHOD, KEY_STATUS, KEY_ERROR))),
+ View.create(Name.create("ocjavametrics/lines_in"), "The number of lines read in from standard input", M_LINE_LENGTHS, countAggregation, noKeys),
+ View.create(Name.create("ocjavametrics/line_lengths"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
};
// Create the view manager
@@ -962,14 +1023,15 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+ // The tag "status"
+ private static final TagKey KEY_STATUS = TagKey.create("status");
+ // The tag "error"
+ private static final TagKey KEY_ERROR = TagKey.create("error");
private static final Tagger tagger = Tags.getTagger();
private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
@@ -978,13 +1040,23 @@ public class Repl {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
+ long startTimeNs = System.nanoTime();
+
try {
readEvaluateProcessLine(stdin);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
} catch (IOException e) {
System.err.println("EOF bye "+ e);
return;
} catch (Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS, KEY_ERROR};
+ String[] tagValues = {"repl", "ERROR", e.getMessage()};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
+ return;
}
}
}
@@ -1007,15 +1079,27 @@ public class Repl {
}
}
+ private static void recordTaggedStat(TagKey[] keys, String[] values, MeasureDouble md, Double d) {
+ TagContextBuilder builder = tagger.emptyBuilder();
+ for (int i = 0; i < keys.length; i++) {
+ builder.put(keys[i], TagValue.create(values[i]));
+ }
+ TagContext tctx = builder.build();
+
+ try (Scope ss = tagger.withTagContext(tctx)) {
+ statsRecorder.newMeasureMap().put(md, d).record();
+ }
+ }
+
private static String processLine(String line) {
long startTimeNs = System.nanoTime();
try {
return line.toUpperCase();
} finally {
- long totalTimeNs = System.nanoTime() - startTimeNs;
- double timespentMs = (new Double(totalTimeNs))/1e6;
- recordTaggedStat(KEY_METHOD, "processLine", M_LATENCY_MS, timespentMs);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS, sinceInMilliseconds(startTimeNs));
}
}
@@ -1023,13 +1107,11 @@ public class Repl {
System.out.print("> ");
System.out.flush();
- try {
- String line = in.readLine();
- String processed = processLine(line);
- System.out.println("< " + processed + "\n");
+ String line = in.readLine();
+ String processed = processLine(line);
+ System.out.println("< " + processed + "\n");
+ if (line != null && line.length() > 0) {
recordStat(M_LINE_LENGTHS, new Long(line.length()));
- } catch(Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
}
}
@@ -1055,10 +1137,9 @@ public class Repl {
// Define the views
View[] views = new View[]{
- View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.singletonList(KEY_METHOD)),
+ View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.unmodifiableList(Arrays.asList(KEY_METHOD, KEY_STATUS, KEY_ERROR))),
View.create(Name.create("ocjavametrics/lines_in"), "The number of lines read in from standard input", M_LINE_LENGTHS, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/errors"), "The number of errors encountered", M_ERRORS, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/line_length"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
+ View.create(Name.create("ocjavametrics/line_lengths"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
};
// Create the view manager
@@ -1089,13 +1170,23 @@ public static void main(String ...args) {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
+ long startTimeNs = System.nanoTime();
+
try {
readEvaluateProcessLine(stdin);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
} catch (IOException e) {
System.err.println("EOF bye "+ e);
return;
} catch (Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS, KEY_ERROR};
+ String[] tagValues = {"repl", "ERROR", e.getMessage()};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
+ return;
}
}
}
@@ -1142,14 +1233,15 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+ // The tag "status"
+ private static final TagKey KEY_STATUS = TagKey.create("status");
+ // The tag "error"
+ private static final TagKey KEY_ERROR = TagKey.create("error");
private static final Tagger tagger = Tags.getTagger();
private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
@@ -1166,13 +1258,23 @@ public class Repl {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
+ long startTimeNs = System.nanoTime();
+
try {
readEvaluateProcessLine(stdin);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
} catch (IOException e) {
System.err.println("EOF bye "+ e);
return;
} catch (Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS, KEY_ERROR};
+ String[] tagValues = {"repl", "ERROR", e.getMessage()};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
+ return;
}
}
}
@@ -1195,15 +1297,27 @@ public class Repl {
}
}
+ private static void recordTaggedStat(TagKey[] keys, String[] values, MeasureDouble md, Double d) {
+ TagContextBuilder builder = tagger.emptyBuilder();
+ for (int i = 0; i < keys.length; i++) {
+ builder.put(keys[i], TagValue.create(values[i]));
+ }
+ TagContext tctx = builder.build();
+
+ try (Scope ss = tagger.withTagContext(tctx)) {
+ statsRecorder.newMeasureMap().put(md, d).record();
+ }
+ }
+
private static String processLine(String line) {
long startTimeNs = System.nanoTime();
try {
return line.toUpperCase();
} finally {
- long totalTimeNs = System.nanoTime() - startTimeNs;
- double timespentMs = (new Double(totalTimeNs))/1e6;
- recordTaggedStat(KEY_METHOD, "processLine", M_LATENCY_MS, timespentMs);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS, sinceInMilliseconds(startTimeNs));
}
}
@@ -1211,13 +1325,11 @@ public class Repl {
System.out.print("> ");
System.out.flush();
- try {
- String line = in.readLine();
- String processed = processLine(line);
- System.out.println("< " + processed + "\n");
+ String line = in.readLine();
+ String processed = processLine(line);
+ System.out.println("< " + processed + "\n");
+ if (line != null && line.length() > 0) {
recordStat(M_LINE_LENGTHS, new Long(line.length()));
- } catch(Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
}
}
@@ -1243,10 +1355,9 @@ public class Repl {
// Define the views
View[] views = new View[]{
- View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.singletonList(KEY_METHOD)),
+ View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.unmodifiableList(Arrays.asList(KEY_METHOD, KEY_STATUS, KEY_ERROR))),
View.create(Name.create("ocjavametrics/lines_in"), "The number of lines read in from standard input", M_LINE_LENGTHS, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/errors"), "The number of errors encountered", M_ERRORS, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/line_length"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
+ View.create(Name.create("ocjavametrics/line_lengths"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
};
// Create the view manager
@@ -1423,14 +1534,15 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+ // The tag "status"
+ private static final TagKey KEY_STATUS = TagKey.create("status");
+ // The tag "error"
+ private static final TagKey KEY_ERROR = TagKey.create("error");
private static final Tagger tagger = Tags.getTagger();
private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
@@ -1447,13 +1559,23 @@ public class Repl {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
+ long startTimeNs = System.nanoTime();
+
try {
readEvaluateProcessLine(stdin);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
} catch (IOException e) {
System.err.println("EOF bye "+ e);
return;
} catch (Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS, KEY_ERROR};
+ String[] tagValues = {"repl", "ERROR", e.getMessage()};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
+ return;
}
}
}
@@ -1476,15 +1598,27 @@ public class Repl {
}
}
+ private static void recordTaggedStat(TagKey[] keys, String[] values, MeasureDouble md, Double d) {
+ TagContextBuilder builder = tagger.emptyBuilder();
+ for (int i = 0; i < keys.length; i++) {
+ builder.put(keys[i], TagValue.create(values[i]));
+ }
+ TagContext tctx = builder.build();
+
+ try (Scope ss = tagger.withTagContext(tctx)) {
+ statsRecorder.newMeasureMap().put(md, d).record();
+ }
+ }
+
private static String processLine(String line) {
long startTimeNs = System.nanoTime();
try {
return line.toUpperCase();
} finally {
- long totalTimeNs = System.nanoTime() - startTimeNs;
- double timespentMs = (new Double(totalTimeNs))/1e6;
- recordTaggedStat(KEY_METHOD, "processLine", M_LATENCY_MS, timespentMs);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS, sinceInMilliseconds(startTimeNs));
}
}
@@ -1492,13 +1626,11 @@ public class Repl {
System.out.print("> ");
System.out.flush();
- try {
- String line = in.readLine();
- String processed = processLine(line);
- System.out.println("< " + processed + "\n");
+ String line = in.readLine();
+ String processed = processLine(line);
+ System.out.println("< " + processed + "\n");
+ if (line != null && line.length() > 0) {
recordStat(M_LINE_LENGTHS, new Long(line.length()));
- } catch(Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
}
}
@@ -1524,10 +1656,9 @@ public class Repl {
// Define the views
View[] views = new View[]{
- View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.singletonList(KEY_METHOD)),
+ View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.unmodifiableList(Arrays.asList(KEY_METHOD, KEY_STATUS, KEY_ERROR))),
View.create(Name.create("ocjavametrics/lines_in"), "The number of lines read in from standard input", M_LINE_LENGTHS, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/errors"), "The number of errors encountered", M_ERRORS, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/line_length"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
+ View.create(Name.create("ocjavametrics/line_lengths"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
};
// Create the view manager
@@ -1604,14 +1735,15 @@ public class Repl {
// The latency in milliseconds
private static final MeasureDouble M_LATENCY_MS = MeasureDouble.create("repl/latency", "The latency in milliseconds per REPL loop", "ms");
- // Counts the number of non EOF(end-of-file) errors.
- private static final MeasureLong M_ERRORS = MeasureLong.create("repl/errors", "The number of errors encountered", "1");
-
// Counts/groups the lengths of lines read in.
private static final MeasureLong M_LINE_LENGTHS = MeasureLong.create("repl/line_lengths", "The distribution of line lengths", "By");
// The tag "method"
private static final TagKey KEY_METHOD = TagKey.create("method");
+ // The tag "status"
+ private static final TagKey KEY_STATUS = TagKey.create("status");
+ // The tag "error"
+ private static final TagKey KEY_ERROR = TagKey.create("error");
private static final Tagger tagger = Tags.getTagger();
private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
@@ -1628,13 +1760,22 @@ public class Repl {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
+ long startTimeNs = System.nanoTime();
+
try {
readEvaluateProcessLine(stdin);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
} catch (IOException e) {
System.err.println("EOF bye "+ e);
return;
} catch (Exception e) {
- recordTaggedStat(KEY_METHOD, "repl", M_ERRORS, new Long(1));
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS, KEY_ERROR};
+ String[] tagValues = {"repl", "ERROR", e.getMessage()};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS,
+ sinceInMilliseconds(startTimeNs));
return;
}
}
@@ -1661,21 +1802,34 @@ public class Repl {
}
}
+ private static void recordTaggedStat(TagKey[] keys, String[] values, MeasureDouble md, Double d) {
+ TagContextBuilder builder = tagger.emptyBuilder();
+ for (int i = 0; i < keys.length; i++) {
+ builder.put(keys[i], TagValue.create(values[i]));
+ }
+ TagContext tctx = builder.build();
+
+ try (Scope ss = tagger.withTagContext(tctx)) {
+ statsRecorder.newMeasureMap().put(md, d).record();
+ }
+ }
+
private static String processLine(String line) {
long startTimeNs = System.nanoTime();
try {
return line.toUpperCase();
- } catch (Exception e) {
- recordTaggedStat(KEY_METHOD, "processLine", M_ERRORS, new Long(1));
- return "";
} finally {
- long totalTimeNs = System.nanoTime() - startTimeNs;
- double timespentMs = (new Double(totalTimeNs))/1e6;
- recordTaggedStat(KEY_METHOD, "processLine", M_LATENCY_MS, timespentMs);
+ TagKey[] tagKeys = {KEY_METHOD, KEY_STATUS};
+ String[] tagValues = {"repl", "OK"};
+ recordTaggedStat(tagKeys, tagValues, M_LATENCY_MS, sinceInMilliseconds(startTimeNs));
}
}
+ private static double sinceInMilliseconds(long startTimeNs) {
+ return (new Double(System.nanoTime() - startTimeNs))/1e6;
+ }
+
private static void readEvaluateProcessLine(BufferedReader in) throws IOException {
System.out.print("> ");
System.out.flush();
@@ -1710,9 +1864,8 @@ public class Repl {
// Define the views
View[] views = new View[]{
- View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.singletonList(KEY_METHOD)),
+ View.create(Name.create("ocjavametrics/latency"), "The distribution of latencies", M_LATENCY_MS, latencyDistribution, Collections.unmodifiableList(Arrays.asList(KEY_METHOD, KEY_STATUS, KEY_ERROR))),
View.create(Name.create("ocjavametrics/lines_in"), "The number of lines read in from standard input", M_LINE_LENGTHS, countAggregation, noKeys),
- View.create(Name.create("ocjavametrics/errors"), "The number of errors encountered", M_ERRORS, countAggregation, Collections.singletonList(KEY_METHOD)),
View.create(Name.create("ocjavametrics/line_lengths"), "The distribution of line lengths", M_LINE_LENGTHS, lengthsDistribution, noKeys)
};