123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- // Copyright 2019, OpenCensus Authors
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- // START entire
- // This example shows how to use gauge metrics. The program records two gauges, one to demonstrate
- // a gauge with int64 value and the other to demonstrate a gauge with float64 value.
- //
- // Metrics
- //
- // 1. process_heap_alloc (int64): Total bytes used by objects allocated in the heap.
- // It includes objects currently used and objects that are freed but not garbage collected.
- //
- // 2. process_heap_idle_to_alloc_ratio (float64): It is the ratio of Idle bytes to allocated
- // bytes in the heap.
- //
- // It periodically runs a function that retrieves the memory stats and updates the above two
- // metrics. These metrics are then exported using log exporter.
- // The program lets you choose the amount of memory (in MB) to consume. Choose different values
- // and query the metrics to see the change in metrics.
- package main
- import (
- "bufio"
- "fmt"
- "log"
- "os"
- "runtime"
- "strconv"
- "strings"
- "time"
- "go.opencensus.io/examples/exporter"
- "go.opencensus.io/metric"
- "go.opencensus.io/metric/metricdata"
- "go.opencensus.io/metric/metricproducer"
- )
- const (
- metricsLogFile = "/tmp/metrics.log"
- )
- var (
- mem = &runtime.MemStats{}
- )
- type memObj struct {
- size int
- b []byte
- }
- func newMemObj(size int) *memObj {
- n := &memObj{size: size, b: make([]byte, size)}
- for i := 0; i < n.size; i++ {
- n.b[i] = byte(i)
- }
- return n
- }
- var allocEntry *metric.Int64GaugeEntry
- var ratioEntry *metric.Float64Entry
- var arr []*memObj
- func getAlloc() uint64 {
- runtime.ReadMemStats(mem)
- return mem.HeapAlloc
- }
- func getIdleToAllocRatio() float64 {
- runtime.ReadMemStats(mem)
- return float64(mem.HeapIdle) / float64(mem.HeapAlloc)
- }
- func consumeMem(sizeMB int) {
- arr = make([]*memObj, sizeMB)
- for i := 0; i < sizeMB; i++ {
- arr = append(arr, newMemObj(1000000))
- }
- }
- func doSomeWork(sizeMB int) {
- // do some work
- consumeMem(sizeMB)
- }
- func recordMetrics(delay int, done chan int) {
- tick := time.NewTicker(time.Duration(delay) * time.Second)
- for {
- select {
- case <-done:
- return
- case <-tick.C:
- // record heap allocation and idle to allocation ratio.
- // START record
- allocEntry.Set(int64(getAlloc())) // int64 gauge
- ratioEntry.Set(getIdleToAllocRatio()) // float64 gauge
- // END record
- }
- }
- }
- func getInput() int {
- reader := bufio.NewReader(os.Stdin)
- limit := 50
- for {
- fmt.Printf("Enter memory (in MB between 1-%d): ", limit)
- text, _ := reader.ReadString('\n')
- sizeMB, err := strconv.Atoi(strings.TrimSuffix(text, "\n"))
- if err == nil {
- if sizeMB < 1 || sizeMB > limit {
- fmt.Printf("invalid value %s\n", text)
- continue
- }
- fmt.Printf("consuming %dMB\n", sizeMB)
- return sizeMB
- }
- fmt.Printf("error %v\n", err)
- }
- }
- func work() {
- fmt.Printf("Program periodically records following gauge metrics.\n")
- fmt.Printf(" 1. process_heap_alloc = the heap allocation (used + freed but not garbage collected)\n")
- fmt.Printf(" 2. process_idle_to_alloc_ratio = heap idle (unused) /allocation ratio\n")
- fmt.Printf("\nGo to file://%s to see the metrics. OR do `tail -f %s` in another terminal\n\n\n",
- metricsLogFile, metricsLogFile)
- fmt.Printf("Enter memory you would like to allocate in MB to change the value of above metrics.\n")
- // Do some work and record gauge metrics.
- for {
- sizeMB := getInput()
- doSomeWork(sizeMB)
- fmt.Printf("press CTRL+C to terminate the program\n")
- }
- }
- func main() {
- // Using log exporter to export metrics but you can choose any supported exporter.
- exporter, err := exporter.NewLogExporter(exporter.Options{
- ReportingInterval: time.Duration(10 * time.Second),
- MetricsLogFile: metricsLogFile,
- })
- if err != nil {
- log.Fatalf("Error creating log exporter: %v", err)
- }
- exporter.Start()
- defer exporter.Stop()
- defer exporter.Close()
- // Create metric registry and register it with global producer manager.
- // START reg
- r := metric.NewRegistry()
- metricproducer.GlobalManager().AddProducer(r)
- // END reg
- // Create Int64Gauge to report memory usage of a process.
- // START alloc
- allocGauge, err := r.AddInt64Gauge(
- "process_heap_alloc",
- metric.WithDescription("Process heap allocation"),
- metric.WithUnit(metricdata.UnitBytes))
- if err != nil {
- log.Fatalf("error creating heap allocation gauge, error %v\n", err)
- }
- // END alloc
- // START entryAlloc
- allocEntry, err = allocGauge.GetEntry()
- if err != nil {
- log.Fatalf("error getting heap allocation gauge entry, error %v\n", err)
- }
- // END entryAlloc
- // Create Float64Gauge to report fractional cpu consumed by Garbage Collection.
- // START idle
- ratioGauge, err := r.AddFloat64Gauge(
- "process_heap_idle_to_alloc_ratio",
- metric.WithDescription("process heap idle to allocate ratio"),
- metric.WithUnit(metricdata.UnitDimensionless))
- if err != nil {
- log.Fatalf("error creating process heap idle to allocate ratio gauge, error %v\n", err)
- }
- // END idle
- // START entryIdle
- ratioEntry, err = ratioGauge.GetEntry()
- if err != nil {
- log.Fatalf("error getting process heap idle to allocate ratio gauge entry, error %v\n", err)
- }
- // END entryIdle
- // record gauge metrics every 5 seconds. This example records the gauges periodically. However,
- // depending on the application it can be non-periodic and can be recorded at any time.
- done := make(chan int)
- defer close(done)
- go recordMetrics(1, done)
- // do your work.
- work()
- }
- // END entire
|