...

Source file src/go.opencensus.io/examples/exporter/logexporter.go

Documentation: go.opencensus.io/examples/exporter

     1  // Copyright 2019, OpenCensus Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package exporter contains a log exporter that supports exporting
    16  // OpenCensus metrics and spans to a logging framework.
    17  package exporter // import "go.opencensus.io/examples/exporter"
    18  
    19  import (
    20  	"context"
    21  	"encoding/hex"
    22  	"fmt"
    23  	"log"
    24  	"os"
    25  	"sync"
    26  	"time"
    27  
    28  	"go.opencensus.io/metric/metricdata"
    29  	"go.opencensus.io/metric/metricexport"
    30  	"go.opencensus.io/trace"
    31  )
    32  
    33  // LogExporter exports metrics and span to log file
    34  type LogExporter struct {
    35  	reader         *metricexport.Reader
    36  	ir             *metricexport.IntervalReader
    37  	initReaderOnce sync.Once
    38  	o              Options
    39  	tFile          *os.File
    40  	mFile          *os.File
    41  	tLogger        *log.Logger
    42  	mLogger        *log.Logger
    43  }
    44  
    45  // Options provides options for LogExporter
    46  type Options struct {
    47  	// ReportingInterval is a time interval between two successive metrics
    48  	// export.
    49  	ReportingInterval time.Duration
    50  
    51  	// MetricsLogFile is path where exported metrics are logged.
    52  	// If it is nil then the metrics are logged on console
    53  	MetricsLogFile string
    54  
    55  	// TracesLogFile is path where exported span data are logged.
    56  	// If it is nil then the span data are logged on console
    57  	TracesLogFile string
    58  }
    59  
    60  func getLogger(filepath string) (*log.Logger, *os.File, error) {
    61  	if filepath == "" {
    62  		return log.New(os.Stdout, "", 0), nil, nil
    63  	}
    64  	f, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
    65  	if err != nil {
    66  		return nil, nil, err
    67  	}
    68  	return log.New(f, "", 0), f, nil
    69  }
    70  
    71  // NewLogExporter creates new log exporter.
    72  func NewLogExporter(options Options) (*LogExporter, error) {
    73  	e := &LogExporter{reader: metricexport.NewReader(),
    74  		o: options}
    75  	var err error
    76  	e.tLogger, e.tFile, err = getLogger(options.TracesLogFile)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	e.mLogger, e.mFile, err = getLogger(options.MetricsLogFile)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  	return e, nil
    85  }
    86  
    87  func printMetricDescriptor(metric *metricdata.Metric) string {
    88  	d := metric.Descriptor
    89  	return fmt.Sprintf("name: %s, type: %s, unit: %s ",
    90  		d.Name, d.Type, d.Unit)
    91  }
    92  
    93  func printLabels(metric *metricdata.Metric, values []metricdata.LabelValue) string {
    94  	d := metric.Descriptor
    95  	kv := []string{}
    96  	for i, k := range d.LabelKeys {
    97  		kv = append(kv, fmt.Sprintf("%s=%v", k, values[i]))
    98  	}
    99  	return fmt.Sprintf("%v", kv)
   100  }
   101  
   102  func printPoint(point metricdata.Point) string {
   103  	switch v := point.Value.(type) {
   104  	case *metricdata.Distribution:
   105  		dv := v
   106  		return fmt.Sprintf("count=%v sum=%v sum_sq_dev=%v, buckets=%v", dv.Count,
   107  			dv.Sum, dv.SumOfSquaredDeviation, dv.Buckets)
   108  	default:
   109  		return fmt.Sprintf("value=%v", point.Value)
   110  	}
   111  }
   112  
   113  // Start starts the metric and span data exporter.
   114  func (e *LogExporter) Start() error {
   115  	trace.RegisterExporter(e)
   116  	e.initReaderOnce.Do(func() {
   117  		e.ir, _ = metricexport.NewIntervalReader(&metricexport.Reader{}, e)
   118  	})
   119  	e.ir.ReportingInterval = e.o.ReportingInterval
   120  	return e.ir.Start()
   121  }
   122  
   123  // Stop stops the metric and span data exporter.
   124  func (e *LogExporter) Stop() {
   125  	trace.UnregisterExporter(e)
   126  	e.ir.Stop()
   127  }
   128  
   129  // Close closes any files that were opened for logging.
   130  func (e *LogExporter) Close() {
   131  	if e.tFile != nil {
   132  		e.tFile.Close()
   133  		e.tFile = nil
   134  	}
   135  	if e.mFile != nil {
   136  		e.mFile.Close()
   137  		e.mFile = nil
   138  	}
   139  }
   140  
   141  // ExportMetrics exports to log.
   142  func (e *LogExporter) ExportMetrics(ctx context.Context, metrics []*metricdata.Metric) error {
   143  	for _, metric := range metrics {
   144  		for _, ts := range metric.TimeSeries {
   145  			for _, point := range ts.Points {
   146  				e.mLogger.Println("#----------------------------------------------")
   147  				e.mLogger.Println()
   148  				e.mLogger.Printf("Metric: %s\n  Labels: %s\n    Value : %s\n",
   149  					printMetricDescriptor(metric),
   150  					printLabels(metric, ts.LabelValues),
   151  					printPoint(point))
   152  				e.mLogger.Println()
   153  			}
   154  		}
   155  	}
   156  	return nil
   157  }
   158  
   159  // ExportSpan exports a SpanData to log
   160  func (e *LogExporter) ExportSpan(sd *trace.SpanData) {
   161  	var (
   162  		traceID      = hex.EncodeToString(sd.SpanContext.TraceID[:])
   163  		spanID       = hex.EncodeToString(sd.SpanContext.SpanID[:])
   164  		parentSpanID = hex.EncodeToString(sd.ParentSpanID[:])
   165  	)
   166  	e.tLogger.Println()
   167  	e.tLogger.Println("#----------------------------------------------")
   168  	e.tLogger.Println()
   169  	e.tLogger.Println("TraceID:     ", traceID)
   170  	e.tLogger.Println("SpanID:      ", spanID)
   171  	if !reZero.MatchString(parentSpanID) {
   172  		e.tLogger.Println("ParentSpanID:", parentSpanID)
   173  	}
   174  
   175  	e.tLogger.Println()
   176  	e.tLogger.Printf("Span:    %v\n", sd.Name)
   177  	e.tLogger.Printf("Status:  %v [%v]\n", sd.Status.Message, sd.Status.Code)
   178  	e.tLogger.Printf("Elapsed: %v\n", sd.EndTime.Sub(sd.StartTime).Round(time.Millisecond))
   179  
   180  	spanKinds := map[int]string{
   181  		1: "Server",
   182  		2: "Client",
   183  	}
   184  	if spanKind, ok := spanKinds[sd.SpanKind]; ok {
   185  		e.tLogger.Printf("SpanKind: %s\n", spanKind)
   186  	}
   187  
   188  	if len(sd.Annotations) > 0 {
   189  		e.tLogger.Println()
   190  		e.tLogger.Println("Annotations:")
   191  		for _, item := range sd.Annotations {
   192  			e.tLogger.Print(indent, item.Message)
   193  			for k, v := range item.Attributes {
   194  				e.tLogger.Printf(" %v=%v", k, v)
   195  			}
   196  			e.tLogger.Println()
   197  		}
   198  	}
   199  
   200  	if len(sd.Attributes) > 0 {
   201  		e.tLogger.Println()
   202  		e.tLogger.Println("Attributes:")
   203  		for k, v := range sd.Attributes {
   204  			e.tLogger.Printf("%v- %v=%v\n", indent, k, v)
   205  		}
   206  	}
   207  
   208  	if len(sd.MessageEvents) > 0 {
   209  		eventTypes := map[trace.MessageEventType]string{
   210  			trace.MessageEventTypeSent: "Sent",
   211  			trace.MessageEventTypeRecv: "Received",
   212  		}
   213  		e.tLogger.Println()
   214  		e.tLogger.Println("MessageEvents:")
   215  		for _, item := range sd.MessageEvents {
   216  			if eventType, ok := eventTypes[item.EventType]; ok {
   217  				e.tLogger.Print(eventType)
   218  			}
   219  			e.tLogger.Printf("UncompressedByteSize: %v", item.UncompressedByteSize)
   220  			e.tLogger.Printf("CompressedByteSize: %v", item.CompressedByteSize)
   221  			e.tLogger.Println()
   222  		}
   223  	}
   224  }
   225  

View as plain text