Repository: census-instrumentation/opencensus-go
Pull request #1124 (2019-04-22 17:23:19)

Remove deprecated exemplar package.
The original exemplar dependency has already been removed from ocagent exporter (https://github.com/census-ecosystem/opencensus-go-exporter-ocagent/pull/53) and stackdriver exporter (https://github.com/census-ecosystem/opencensus-go-exporter-stackdriver/pull/112).


Patch:
diff --git a/examples/exporter/logexporter.go b/examples/exporter/logexporter.go
index d868b5a..3b9159d 100644
--- a/examples/exporter/logexporter.go
+++ b/examples/exporter/logexporter.go
@@ -177,6 +177,14 @@ func (e *LogExporter) ExportSpan(sd *trace.SpanData) {
 	e.tLogger.Printf("Status:  %v [%v]\n", sd.Status.Message, sd.Status.Code)
 	e.tLogger.Printf("Elapsed: %v\n", sd.EndTime.Sub(sd.StartTime).Round(time.Millisecond))
 
+	spanKinds := map[int]string{
+		1: "Server",
+		2: "Client",
+	}
+	if spanKind, ok := spanKinds[sd.SpanKind]; ok {
+		e.tLogger.Printf("SpanKind: %s\n", spanKind)
+	}
+
 	if len(sd.Annotations) > 0 {
 		e.tLogger.Println()
 		e.tLogger.Println("Annotations:")
@@ -196,4 +204,21 @@ func (e *LogExporter) ExportSpan(sd *trace.SpanData) {
 			e.tLogger.Printf("%v- %v=%v\n", indent, k, v)
 		}
 	}
+
+	if len(sd.MessageEvents) > 0 {
+		eventTypes := map[trace.MessageEventType]string{
+			trace.MessageEventTypeSent: "Sent",
+			trace.MessageEventTypeRecv: "Received",
+		}
+		e.tLogger.Println()
+		e.tLogger.Println("MessageEvents:")
+		for _, item := range sd.MessageEvents {
+			if eventType, ok := eventTypes[item.EventType]; ok {
+				e.tLogger.Print(eventType)
+			}
+			e.tLogger.Printf("UncompressedByteSize: %v", item.UncompressedByteSize)
+			e.tLogger.Printf("CompressedByteSize: %v", item.CompressedByteSize)
+			e.tLogger.Println()
+		}
+	}
 }
diff --git a/examples/http/helloworld_server/main.go b/examples/http/helloworld_server/main.go
index 16ed552..551915d 100644
--- a/examples/http/helloworld_server/main.go
+++ b/examples/http/helloworld_server/main.go
@@ -28,6 +28,11 @@ import (
 	"go.opencensus.io/trace"
 )
 
+const (
+	metricsLogFile = "/tmp/metrics.log"
+	tracesLogFile  = "/tmp/trace.log"
+)
+
 func main() {
 	// Start z-Pages server.
 	go func() {
@@ -36,10 +41,18 @@ func main() {
 		log.Fatal(http.ListenAndServe("127.0.0.1:8081", mux))
 	}()
 
-	// Register stats and trace exporters to export the collected data.
-	exporter := &exporter.PrintExporter{}
-	view.RegisterExporter(exporter)
-	trace.RegisterExporter(exporter)
+	// 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,
+		TracesLogFile:     tracesLogFile,
+	})
+	if err != nil {
+		log.Fatalf("Error creating log exporter: %v", err)
+	}
+	exporter.Start()
+	defer exporter.Stop()
+	defer exporter.Close()
 
 	// Always trace for this demo. In a production application, you should
 	// configure this to a trace.ProbabilitySampler set at the desired
diff --git a/examples/quickstart/stats.go b/examples/quickstart/stats.go
index 3520877..7e97351 100644
--- a/examples/quickstart/stats.go
+++ b/examples/quickstart/stats.go
@@ -90,7 +90,7 @@ var (
 		Description: "Groups the lengths of keys in buckets",
 		Measure:     mLineLengths,
 		// Lengths: [>=0B, >=5B, >=10B, >=15B, >=20B, >=40B, >=60B, >=80, >=100B, >=200B, >=400, >=600, >=800, >=1000]
-		Aggregation: view.Distribution(5, 2000, 15, 20, 40, 60, 80, 100, 200, 400, 600, 800, 1000),
+		Aggregation: view.Distribution(5, 10, 15, 20, 40, 60, 80, 100, 200, 400, 600, 800, 1000),
 	}
 )
 
diff --git a/exemplar/exemplar.go b/exemplar/exemplar.go
deleted file mode 100644
index 5a4c434..0000000
--- a/exemplar/exemplar.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2018, 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.
-
-// Package exemplar implements support for exemplars. Exemplars are additional
-// data associated with each measurement.
-//
-// Their purpose it to provide an example of the kind of thing
-// (request, RPC, trace span, etc.) that resulted in that measurement.
-//
-// Deprecated: Use go.opencensus.io/metric/metricdata instead.
-package exemplar
-
-import (
-	"context"
-	"time"
-)
-
-// Exemplars keys.
-const (
-	KeyTraceID   = "trace_id"
-	KeySpanID    = "span_id"
-	KeyPrefixTag = "tag:"
-)
-
-// Exemplar is an example data point associated with each bucket of a
-// distribution type aggregation.
-//
-// Deprecated: Use go.opencensus.io/metric/metricdata/exemplar instead.
-type Exemplar struct {
-	Value       float64     // the value that was recorded
-	Timestamp   time.Time   // the time the value was recorded
-	Attachments Attachments // attachments (if any)
-}
-
-// Attachments is a map of extra values associated with a recorded data point.
-// The map should only be mutated from AttachmentExtractor functions.
-type Attachments map[string]string
-
-// AttachmentExtractor is a function capable of extracting exemplar attachments
-// from the context used to record measurements.
-// The map passed to the function should be mutated and returned. It will
-// initially be nil: the first AttachmentExtractor that would like to add keys to the
-// map is responsible for initializing it.
-type AttachmentExtractor func(ctx context.Context, a Attachments) Attachments
-
-var extractors []AttachmentExtractor
-
-// RegisterAttachmentExtractor registers the given extractor associated with the exemplar
-// type name.
-//
-// Extractors will be used to attempt to extract exemplars from the context
-// associated with each recorded measurement.
-//
-// Packages that support exemplars should register their extractor functions on
-// initialization.
-//
-// RegisterAttachmentExtractor should not be called after any measurements have
-// been recorded.
-func RegisterAttachmentExtractor(e AttachmentExtractor) {
-	extractors = append(extractors, e)
-}
-
-// AttachmentsFromContext extracts exemplars from the given context.
-// Each registered AttachmentExtractor (see RegisterAttachmentExtractor) is called in an
-// unspecified order to add attachments to the exemplar.
-func AttachmentsFromContext(ctx context.Context) Attachments {
-	var a Attachments
-	for _, extractor := range extractors {
-		a = extractor(ctx, a)
-	}
-	return a
-}
diff --git a/exporter/jaeger/agent.go b/exporter/jaeger/agent.go
deleted file mode 100644
index 4c8cd98..0000000
--- a/exporter/jaeger/agent.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2018, 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.
-
-package jaeger
-
-import (
-	"fmt"
-	"io"
-	"net"
-
-	"github.com/apache/thrift/lib/go/thrift"
-	gen "go.opencensus.io/exporter/jaeger/internal/gen-go/jaeger"
-)
-
-// udpPacketMaxLength is the max size of UDP packet we want to send, synced with jaeger-agent
-const udpPacketMaxLength = 65000
-
-// agentClientUDP is a UDP client to Jaeger agent that implements gen.Agent interface.
-type agentClientUDP struct {
-	gen.Agent
-	io.Closer
-
-	connUDP       *net.UDPConn
-	client        *gen.AgentClient
-	maxPacketSize int                   // max size of datagram in bytes
-	thriftBuffer  *thrift.TMemoryBuffer // buffer used to calculate byte size of a span
-}
-
-// newAgentClientUDP creates a client that sends spans to Jaeger Agent over UDP.
-func newAgentClientUDP(hostPort string, maxPacketSize int) (*agentClientUDP, error) {
-	if maxPacketSize == 0 {
-		maxPacketSize = udpPacketMaxLength
-	}
-
-	thriftBuffer := thrift.NewTMemoryBufferLen(maxPacketSize)
-	protocolFactory := thrift.NewTCompactProtocolFactory()
-	client := gen.NewAgentClientFactory(thriftBuffer, protocolFactory)
-
-	destAddr, err := net.ResolveUDPAddr("udp", hostPort)
-	if err != nil {
-		return nil, err
-	}
-
-	connUDP, err := net.DialUDP(destAddr.Network(), nil, destAddr)
-	if err != nil {
-		return nil, err
-	}
-	if err := connUDP.SetWriteBuffer(maxPacketSize); err != nil {
-		return nil, err
-	}
-
-	clientUDP := &agentClientUDP{
-		connUDP:       connUDP,
-		client:        client,
-		maxPacketSize: maxPacketSize,
-		thriftBuffer:  thriftBuffer}
-	return clientUDP, nil
-}
-
-// EmitBatch implements EmitBatch() of Agent interface
-func (a *agentClientUDP) EmitBatch(batch *gen.Batch) error {
-	a.thriftBuffer.Reset()
-	a.client.SeqId = 0 // we have no need for distinct SeqIds for our one-way UDP messages
-	if err := a.client.EmitBatch(batch); err != nil {
-		return err
-	}
-	if a.thriftBuffer.Len() > a.maxPacketSize {
-		return fmt.Errorf("Data does not fit within one UDP packet; size %d, max %d, spans %d",
-			a.thriftBuffer.Len(), a.maxPacketSize, len(batch.Spans))
-	}
-	_, err := a.connUDP.Write(a.thriftBuffer.Bytes())
-	return err
-}
-
-// Close implements Close() of io.Closer and closes the underlying UDP connection.
-func (a *agentClientUDP) Close() error {
-	return a.connUDP.Close()
-}
diff --git a/exporter/jaeger/example/main.go b/exporter/jaeger/example/main.go
deleted file mode 100644
index 12e7a90..0000000
--- a/exporter/jaeger/example/main.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2017, 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.
-
-// Command jaeger is an example program that creates spans
-// and uploads to Jaeger.
-package main
-
-import (
-	"context"
-	"log"
-
-	"go.opencensus.io/exporter/jaeger"
-	"go.opencensus.io/trace"
-)
-
-func main() {
-	ctx := context.Background()
-
-	// Register the Jaeger exporter to be able to retrieve
-	// the collected spans.
-	exporter, err := jaeger.NewExporter(jaeger.Options{
-		CollectorEndpoint: "http://localhost:14268/api/traces",
-		Process: jaeger.Process{
-			ServiceName: "trace-demo",
-		},
-	})
-	if err != nil {
-		log.Fatal(err)
-	}
-	trace.RegisterExporter(exporter)
-
-	// For demoing purposes, always sample. In a production application, you should
-	// configure this to a trace.ProbabilitySampler set at the desired
-	// probability.
-	trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
-
-	ctx, span := trace.StartSpan(ctx, "/foo")
-	bar(ctx)
-	span.End()
-
-	exporter.Flush()
-}
-
-func bar(ctx context.Context) {
-	ctx, span := trace.StartSpan(ctx, "/bar")
-	defer span.End()
-
-	// Do bar...
-}
diff --git a/exporter/jaeger/internal/gen-go/README b/exporter/jaeger/internal/gen-go/README
deleted file mode 100644
index cda0c56..0000000
--- a/exporter/jaeger/internal/gen-go/README
+++ /dev/null
@@ -1,2 +0,0 @@
-Files autogenerated by the Thrift compiler
-from the files at https://github.com/jaegertracing/jaeger-idl.
\ No newline at end of file
diff --git a/exporter/jaeger/internal/gen-go/jaeger/GoUnusedProtection__.go b/exporter/jaeger/internal/gen-go/jaeger/GoUnusedProtection__.go
deleted file mode 100644
index 345a65a..0000000
--- a/exporter/jaeger/internal/gen-go/jaeger/GoUnusedProtection__.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// Autogenerated by Thrift Compiler (0.11.0)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
-
-package jaeger
-
-var GoUnusedProtection__ int
diff --git a/exporter/jaeger/internal/gen-go/jaeger/agent.go b/exporter/jaeger/internal/gen-go/jaeger/agent.go
deleted file mode 100644
index 88d2df5..0000000
--- a/exporter/jaeger/internal/gen-go/jaeger/agent.go
+++ /dev/null
@@ -1,244 +0,0 @@
-// Autogenerated by Thrift Compiler (0.9.3)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
-
-package jaeger
-
-import (
-	"bytes"
-	"context"
-	"fmt"
-
-	"github.com/apache/thrift/lib/go/thrift"
-)
-
-// (needed to ensure safety because of naive import list construction.)
-var _ = thrift.ZERO
-var _ = fmt.Printf
-var _ = bytes.Equal
-
-type Agent interface {
-	// Parameters:
-	//  - Batch
-	EmitBatch(batch *Batch) (err error)
-}
-
-type AgentClient struct {
-	Transport       thrift.TTransport
-	ProtocolFactory thrift.TProtocolFactory
-	InputProtocol   thrift.TProtocol
-	OutputProtocol  thrift.TProtocol
-	SeqId           int32
-}
-
-func NewAgentClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AgentClient {
-	return &AgentClient{Transport: t,
-		ProtocolFactory: f,
-		InputProtocol:   f.GetProtocol(t),
-		OutputProtocol:  f.GetProtocol(t),
-		SeqId:           0,
-	}
-}
-
-func NewAgentClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AgentClient {
-	return &AgentClient{Transport: t,
-		ProtocolFactory: nil,
-		InputProtocol:   iprot,
-		OutputProtocol:  oprot,
-		SeqId:           0,
-	}
-}
-
-// Parameters:
-//  - Batch
-func (p *AgentClient) EmitBatch(batch *Batch) (err error) {
-	if err = p.sendEmitBatch(batch); err != nil {
-		return
-	}
-	return
-}
-
-func (p *AgentClient) sendEmitBatch(batch *Batch) (err error) {
-	oprot := p.OutputProtocol
-	if oprot == nil {
-		oprot = p.ProtocolFactory.GetProtocol(p.Transport)
-		p.OutputProtocol = oprot
-	}
-	p.SeqId++
-	if err = oprot.WriteMessageBegin("emitBatch", thrift.ONEWAY, p.SeqId); err != nil {
-		return
-	}
-	args := AgentEmitBatchArgs{
-		Batch: batch,
-	}
-	if err = args.Write(oprot); err != nil {
-		return
-	}
-	if err = oprot.WriteMessageEnd(); err != nil {
-		return
-	}
-	return oprot.Flush(context.Background())
-}
-
-type AgentProcessor struct {
-	processorMap map[string]thrift.TProcessorFunction
-	handler      Agent
-}
-
-func (p *AgentProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
-	p.processorMap[key] = processor
-}
-
-func (p *AgentProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
-	processor, ok = p.processorMap[key]
-	return processor, ok
-}
-
-func (p *AgentProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
-	return p.processorMap
-}
-
-func NewAgentProcessor(handler Agent) *AgentProcessor {
-
-	self0 := &AgentProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
-	self0.processorMap["emitBatch"] = &agentProcessorEmitBatch{handler: handler}
-	return self0
-}
-
-func (p *AgentProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
-	ctx := context.Background()
-	name, _, seqId, err := iprot.ReadMessageBegin()
-	if err != nil {
-		return false, err
-	}
-	if processor, ok := p.GetProcessorFunction(name); ok {
-		return processor.Process(ctx, seqId, iprot, oprot)
-	}
-	iprot.Skip(thrift.STRUCT)
-	iprot.ReadMessageEnd()
-	x1 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
-	oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
-	x1.Write(oprot)
-	oprot.WriteMessageEnd()
-	oprot.Flush(ctx)
-	return false, x1
-}
-
-type agentProcessorEmitBatch struct {
-	handler Agent
-}
-
-func (p *agentProcessorEmitBatch) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
-	args := AgentEmitBatchArgs{}
-	if err = args.Read(iprot); err != nil {
-		iprot.ReadMessageEnd()
-		return false, err
-	}
-
-	iprot.ReadMessageEnd()
-	var err2 error
-	if err2 = p.handler.EmitBatch(args.Batch); err2 != nil {
-		return true, err2
-	}
-	return true, nil
-}
-
-// HELPER FUNCTIONS AND STRUCTURES
-
-// Attributes:
-//  - Batch
-type AgentEmitBatchArgs struct {
-	Batch *Batch `thrift:"batch,1" json:"batch"`
-}
-
-func NewAgentEmitBatchArgs() *AgentEmitBatchArgs {
-	return &AgentEmitBatchArgs{}
-}
-
-var AgentEmitBatchArgs_Batch_DEFAULT *Batch
-
-func (p *AgentEmitBatchArgs) GetBatch() *Batch {
-	if !p.IsSetBatch() {
-		return AgentEmitBatchArgs_Batch_DEFAULT
-	}
-	return p.Batch
-}
-func (p *AgentEmitBatchArgs) IsSetBatch() bool {
-	return p.Batch != nil
-}
-
-func (p *AgentEmitBatchArgs) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if err := p.readField1(iprot); err != nil {
-				return err
-			}
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	return nil
-}
-
-func (p *AgentEmitBatchArgs) readField1(iprot thrift.TProtocol) error {
-	p.Batch = &Batch{}
-	if err := p.Batch.Read(iprot); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Batch), err)
-	}
-	return nil
-}
-
-func (p *AgentEmitBatchArgs) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("emitBatch_args"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if err := p.writeField1(oprot); err != nil {
-		return err
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *AgentEmitBatchArgs) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("batch", thrift.STRUCT, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batch: ", p), err)
-	}
-	if err := p.Batch.Write(oprot); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Batch), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batch: ", p), err)
-	}
-	return err
-}
-
-func (p *AgentEmitBatchArgs) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("AgentEmitBatchArgs(%+v)", *p)
-}
diff --git a/exporter/jaeger/internal/gen-go/jaeger/collector-remote/collector-remote.go b/exporter/jaeger/internal/gen-go/jaeger/collector-remote/collector-remote.go
deleted file mode 100755
index 157559e..0000000
--- a/exporter/jaeger/internal/gen-go/jaeger/collector-remote/collector-remote.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Autogenerated by Thrift Compiler (0.11.0)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
-
-package main
-
-import (
-	"context"
-	"flag"
-	"fmt"
-	"math"
-	"net"
-	"net/url"
-	"os"
-	"strconv"
-	"strings"
-
-	"github.com/apache/thrift/lib/go/thrift"
-	"go.opencensus.io/exporter/jaeger/internal/gen-go/jaeger"
-)
-
-func Usage() {
-	fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:")
-	flag.PrintDefaults()
-	fmt.Fprintln(os.Stderr, "\nFunctions:")
-	fmt.Fprintln(os.Stderr, "   submitBatches( batches)")
-	fmt.Fprintln(os.Stderr)
-	os.Exit(0)
-}
-
-func main() {
-	flag.Usage = Usage
-	var host string
-	var port int
-	var protocol string
-	var urlString string
-	var framed bool
-	var useHttp bool
-	var parsedUrl *url.URL
-	var trans thrift.TTransport
-	_ = strconv.Atoi
-	_ = math.Abs
-	flag.Usage = Usage
-	flag.StringVar(&host, "h", "localhost", "Specify host and port")
-	flag.IntVar(&port, "p", 9090, "Specify port")
-	flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)")
-	flag.StringVar(&urlString, "u", "", "Specify the url")
-	flag.BoolVar(&framed, "framed", false, "Use framed transport")
-	flag.BoolVar(&useHttp, "http", false, "Use http")
-	flag.Parse()
-
-	if len(urlString) > 0 {
-		var err error
-		parsedUrl, err = url.Parse(urlString)
-		if err != nil {
-			fmt.Fprintln(os.Stderr, "Error parsing URL: ", err)
-			flag.Usage()
-		}
-		host = parsedUrl.Host
-		useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http"
-	} else if useHttp {
-		_, err := url.Parse(fmt.Sprint("http://", host, ":", port))
-		if err != nil {
-			fmt.Fprintln(os.Stderr, "Error parsing URL: ", err)
-			flag.Usage()
-		}
-	}
-
-	cmd := flag.Arg(0)
-	var err error
-	if useHttp {
-		trans, err = thrift.NewTHttpClient(parsedUrl.String())
-	} else {
-		portStr := fmt.Sprint(port)
-		if strings.Contains(host, ":") {
-			host, portStr, err = net.SplitHostPort(host)
-			if err != nil {
-				fmt.Fprintln(os.Stderr, "error with host:", err)
-				os.Exit(1)
-			}
-		}
-		trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr))
-		if err != nil {
-			fmt.Fprintln(os.Stderr, "error resolving address:", err)
-			os.Exit(1)
-		}
-		if framed {
-			trans = thrift.NewTFramedTransport(trans)
-		}
-	}
-	if err != nil {
-		fmt.Fprintln(os.Stderr, "Error creating transport", err)
-		os.Exit(1)
-	}
-	defer trans.Close()
-	var protocolFactory thrift.TProtocolFactory
-	switch protocol {
-	case "compact":
-		protocolFactory = thrift.NewTCompactProtocolFactory()
-		break
-	case "simplejson":
-		protocolFactory = thrift.NewTSimpleJSONProtocolFactory()
-		break
-	case "json":
-		protocolFactory = thrift.NewTJSONProtocolFactory()
-		break
-	case "binary", "":
-		protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
-		break
-	default:
-		fmt.Fprintln(os.Stderr, "Invalid protocol specified: ", protocol)
-		Usage()
-		os.Exit(1)
-	}
-	iprot := protocolFactory.GetProtocol(trans)
-	oprot := protocolFactory.GetProtocol(trans)
-	client := jaeger.NewCollectorClient(thrift.NewTStandardClient(iprot, oprot))
-	if err := trans.Open(); err != nil {
-		fmt.Fprintln(os.Stderr, "Error opening socket to ", host, ":", port, " ", err)
-		os.Exit(1)
-	}
-
-	switch cmd {
-	case "submitBatches":
-		if flag.NArg()-1 != 1 {
-			fmt.Fprintln(os.Stderr, "SubmitBatches requires 1 args")
-			flag.Usage()
-		}
-		arg12 := flag.Arg(1)
-		mbTrans13 := thrift.NewTMemoryBufferLen(len(arg12))
-		defer mbTrans13.Close()
-		_, err14 := mbTrans13.WriteString(arg12)
-		if err14 != nil {
-			Usage()
-			return
-		}
-		factory15 := thrift.NewTSimpleJSONProtocolFactory()
-		jsProt16 := factory15.GetProtocol(mbTrans13)
-		containerStruct0 := jaeger.NewCollectorSubmitBatchesArgs()
-		err17 := containerStruct0.ReadField1(jsProt16)
-		if err17 != nil {
-			Usage()
-			return
-		}
-		argvalue0 := containerStruct0.Batches
-		value0 := argvalue0
-		fmt.Print(client.SubmitBatches(context.Background(), value0))
-		fmt.Print("\n")
-		break
-	case "":
-		Usage()
-		break
-	default:
-		fmt.Fprintln(os.Stderr, "Invalid function ", cmd)
-	}
-}
diff --git a/exporter/jaeger/internal/gen-go/jaeger/jaeger-consts.go b/exporter/jaeger/internal/gen-go/jaeger/jaeger-consts.go
deleted file mode 100644
index d2b0fa9..0000000
--- a/exporter/jaeger/internal/gen-go/jaeger/jaeger-consts.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Autogenerated by Thrift Compiler (0.11.0)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
-
-package jaeger
-
-import (
-	"bytes"
-	"context"
-	"fmt"
-	"reflect"
-
-	"github.com/apache/thrift/lib/go/thrift"
-)
-
-// (needed to ensure safety because of naive import list construction.)
-var _ = thrift.ZERO
-var _ = fmt.Printf
-var _ = context.Background
-var _ = reflect.DeepEqual
-var _ = bytes.Equal
-
-func init() {
-}
diff --git a/exporter/jaeger/internal/gen-go/jaeger/jaeger.go b/exporter/jaeger/internal/gen-go/jaeger/jaeger.go
deleted file mode 100644
index 0f91363..0000000
--- a/exporter/jaeger/internal/gen-go/jaeger/jaeger.go
+++ /dev/null
@@ -1,2443 +0,0 @@
-// Autogenerated by Thrift Compiler (0.11.0)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
-
-package jaeger // import "go.opencensus.io/exporter/jaeger/internal/gen-go/jaeger"
-
-import (
-	"bytes"
-	"context"
-	"database/sql/driver"
-	"errors"
-	"fmt"
-	"reflect"
-
-	"github.com/apache/thrift/lib/go/thrift"
-)
-
-// (needed to ensure safety because of naive import list construction.)
-var _ = thrift.ZERO
-var _ = fmt.Printf
-var _ = context.Background
-var _ = reflect.DeepEqual
-var _ = bytes.Equal
-
-type TagType int64
-
-const (
-	TagType_STRING TagType = 0
-	TagType_DOUBLE TagType = 1
-	TagType_BOOL   TagType = 2
-	TagType_LONG   TagType = 3
-	TagType_BINARY TagType = 4
-)
-
-func (p TagType) String() string {
-	switch p {
-	case TagType_STRING:
-		return "STRING"
-	case TagType_DOUBLE:
-		return "DOUBLE"
-	case TagType_BOOL:
-		return "BOOL"
-	case TagType_LONG:
-		return "LONG"
-	case TagType_BINARY:
-		return "BINARY"
-	}
-	return "<UNSET>"
-}
-
-func TagTypeFromString(s string) (TagType, error) {
-	switch s {
-	case "STRING":
-		return TagType_STRING, nil
-	case "DOUBLE":
-		return TagType_DOUBLE, nil
-	case "BOOL":
-		return TagType_BOOL, nil
-	case "LONG":
-		return TagType_LONG, nil
-	case "BINARY":
-		return TagType_BINARY, nil
-	}
-	return TagType(0), fmt.Errorf("not a valid TagType string")
-}
-
-func TagTypePtr(v TagType) *TagType { return &v }
-
-func (p TagType) MarshalText() ([]byte, error) {
-	return []byte(p.String()), nil
-}
-
-func (p *TagType) UnmarshalText(text []byte) error {
-	q, err := TagTypeFromString(string(text))
-	if err != nil {
-		return err
-	}
-	*p = q
-	return nil
-}
-
-func (p *TagType) Scan(value interface{}) error {
-	v, ok := value.(int64)
-	if !ok {
-		return errors.New("Scan value is not int64")
-	}
-	*p = TagType(v)
-	return nil
-}
-
-func (p *TagType) Value() (driver.Value, error) {
-	if p == nil {
-		return nil, nil
-	}
-	return int64(*p), nil
-}
-
-type SpanRefType int64
-
-const (
-	SpanRefType_CHILD_OF     SpanRefType = 0
-	SpanRefType_FOLLOWS_FROM SpanRefType = 1
-)
-
-func (p SpanRefType) String() string {
-	switch p {
-	case SpanRefType_CHILD_OF:
-		return "CHILD_OF"
-	case SpanRefType_FOLLOWS_FROM:
-		return "FOLLOWS_FROM"
-	}
-	return "<UNSET>"
-}
-
-func SpanRefTypeFromString(s string) (SpanRefType, error) {
-	switch s {
-	case "CHILD_OF":
-		return SpanRefType_CHILD_OF, nil
-	case "FOLLOWS_FROM":
-		return SpanRefType_FOLLOWS_FROM, nil
-	}
-	return SpanRefType(0), fmt.Errorf("not a valid SpanRefType string")
-}
-
-func SpanRefTypePtr(v SpanRefType) *SpanRefType { return &v }
-
-func (p SpanRefType) MarshalText() ([]byte, error) {
-	return []byte(p.String()), nil
-}
-
-func (p *SpanRefType) UnmarshalText(text []byte) error {
-	q, err := SpanRefTypeFromString(string(text))
-	if err != nil {
-		return err
-	}
-	*p = q
-	return nil
-}
-
-func (p *SpanRefType) Scan(value interface{}) error {
-	v, ok := value.(int64)
-	if !ok {
-		return errors.New("Scan value is not int64")
-	}
-	*p = SpanRefType(v)
-	return nil
-}
-
-func (p *SpanRefType) Value() (driver.Value, error) {
-	if p == nil {
-		return nil, nil
-	}
-	return int64(*p), nil
-}
-
-// Attributes:
-//  - Key
-//  - VType
-//  - VStr
-//  - VDouble
-//  - VBool
-//  - VLong
-//  - VBinary
-type Tag struct {
-	Key     string   `thrift:"key,1,required" db:"key" json:"key"`
-	VType   TagType  `thrift:"vType,2,required" db:"vType" json:"vType"`
-	VStr    *string  `thrift:"vStr,3" db:"vStr" json:"vStr,omitempty"`
-	VDouble *float64 `thrift:"vDouble,4" db:"vDouble" json:"vDouble,omitempty"`
-	VBool   *bool    `thrift:"vBool,5" db:"vBool" json:"vBool,omitempty"`
-	VLong   *int64   `thrift:"vLong,6" db:"vLong" json:"vLong,omitempty"`
-	VBinary []byte   `thrift:"vBinary,7" db:"vBinary" json:"vBinary,omitempty"`
-}
-
-func NewTag() *Tag {
-	return &Tag{}
-}
-
-func (p *Tag) GetKey() string {
-	return p.Key
-}
-
-func (p *Tag) GetVType() TagType {
-	return p.VType
-}
-
-var Tag_VStr_DEFAULT string
-
-func (p *Tag) GetVStr() string {
-	if !p.IsSetVStr() {
-		return Tag_VStr_DEFAULT
-	}
-	return *p.VStr
-}
-
-var Tag_VDouble_DEFAULT float64
-
-func (p *Tag) GetVDouble() float64 {
-	if !p.IsSetVDouble() {
-		return Tag_VDouble_DEFAULT
-	}
-	return *p.VDouble
-}
-
-var Tag_VBool_DEFAULT bool
-
-func (p *Tag) GetVBool() bool {
-	if !p.IsSetVBool() {
-		return Tag_VBool_DEFAULT
-	}
-	return *p.VBool
-}
-
-var Tag_VLong_DEFAULT int64
-
-func (p *Tag) GetVLong() int64 {
-	if !p.IsSetVLong() {
-		return Tag_VLong_DEFAULT
-	}
-	return *p.VLong
-}
-
-var Tag_VBinary_DEFAULT []byte
-
-func (p *Tag) GetVBinary() []byte {
-	return p.VBinary
-}
-func (p *Tag) IsSetVStr() bool {
-	return p.VStr != nil
-}
-
-func (p *Tag) IsSetVDouble() bool {
-	return p.VDouble != nil
-}
-
-func (p *Tag) IsSetVBool() bool {
-	return p.VBool != nil
-}
-
-func (p *Tag) IsSetVLong() bool {
-	return p.VLong != nil
-}
-
-func (p *Tag) IsSetVBinary() bool {
-	return p.VBinary != nil
-}
-
-func (p *Tag) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	var issetKey bool = false
-	var issetVType bool = false
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if fieldTypeId == thrift.STRING {
-				if err := p.ReadField1(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetKey = true
-		case 2:
-			if fieldTypeId == thrift.I32 {
-				if err := p.ReadField2(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetVType = true
-		case 3:
-			if fieldTypeId == thrift.STRING {
-				if err := p.ReadField3(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		case 4:
-			if fieldTypeId == thrift.DOUBLE {
-				if err := p.ReadField4(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		case 5:
-			if fieldTypeId == thrift.BOOL {
-				if err := p.ReadField5(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		case 6:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField6(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		case 7:
-			if fieldTypeId == thrift.STRING {
-				if err := p.ReadField7(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	if !issetKey {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Key is not set"))
-	}
-	if !issetVType {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field VType is not set"))
-	}
-	return nil
-}
-
-func (p *Tag) ReadField1(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadString(); err != nil {
-		return thrift.PrependError("error reading field 1: ", err)
-	} else {
-		p.Key = v
-	}
-	return nil
-}
-
-func (p *Tag) ReadField2(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI32(); err != nil {
-		return thrift.PrependError("error reading field 2: ", err)
-	} else {
-		temp := TagType(v)
-		p.VType = temp
-	}
-	return nil
-}
-
-func (p *Tag) ReadField3(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadString(); err != nil {
-		return thrift.PrependError("error reading field 3: ", err)
-	} else {
-		p.VStr = &v
-	}
-	return nil
-}
-
-func (p *Tag) ReadField4(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadDouble(); err != nil {
-		return thrift.PrependError("error reading field 4: ", err)
-	} else {
-		p.VDouble = &v
-	}
-	return nil
-}
-
-func (p *Tag) ReadField5(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadBool(); err != nil {
-		return thrift.PrependError("error reading field 5: ", err)
-	} else {
-		p.VBool = &v
-	}
-	return nil
-}
-
-func (p *Tag) ReadField6(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 6: ", err)
-	} else {
-		p.VLong = &v
-	}
-	return nil
-}
-
-func (p *Tag) ReadField7(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadBinary(); err != nil {
-		return thrift.PrependError("error reading field 7: ", err)
-	} else {
-		p.VBinary = v
-	}
-	return nil
-}
-
-func (p *Tag) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("Tag"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField1(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField2(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField3(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField4(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField5(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField6(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField7(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *Tag) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("key", thrift.STRING, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:key: ", p), err)
-	}
-	if err := oprot.WriteString(string(p.Key)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.key (1) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:key: ", p), err)
-	}
-	return err
-}
-
-func (p *Tag) writeField2(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("vType", thrift.I32, 2); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:vType: ", p), err)
-	}
-	if err := oprot.WriteI32(int32(p.VType)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.vType (2) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:vType: ", p), err)
-	}
-	return err
-}
-
-func (p *Tag) writeField3(oprot thrift.TProtocol) (err error) {
-	if p.IsSetVStr() {
-		if err := oprot.WriteFieldBegin("vStr", thrift.STRING, 3); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:vStr: ", p), err)
-		}
-		if err := oprot.WriteString(string(*p.VStr)); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T.vStr (3) field write error: ", p), err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 3:vStr: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Tag) writeField4(oprot thrift.TProtocol) (err error) {
-	if p.IsSetVDouble() {
-		if err := oprot.WriteFieldBegin("vDouble", thrift.DOUBLE, 4); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:vDouble: ", p), err)
-		}
-		if err := oprot.WriteDouble(float64(*p.VDouble)); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T.vDouble (4) field write error: ", p), err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 4:vDouble: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Tag) writeField5(oprot thrift.TProtocol) (err error) {
-	if p.IsSetVBool() {
-		if err := oprot.WriteFieldBegin("vBool", thrift.BOOL, 5); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 5:vBool: ", p), err)
-		}
-		if err := oprot.WriteBool(bool(*p.VBool)); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T.vBool (5) field write error: ", p), err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 5:vBool: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Tag) writeField6(oprot thrift.TProtocol) (err error) {
-	if p.IsSetVLong() {
-		if err := oprot.WriteFieldBegin("vLong", thrift.I64, 6); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 6:vLong: ", p), err)
-		}
-		if err := oprot.WriteI64(int64(*p.VLong)); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T.vLong (6) field write error: ", p), err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 6:vLong: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Tag) writeField7(oprot thrift.TProtocol) (err error) {
-	if p.IsSetVBinary() {
-		if err := oprot.WriteFieldBegin("vBinary", thrift.STRING, 7); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 7:vBinary: ", p), err)
-		}
-		if err := oprot.WriteBinary(p.VBinary); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T.vBinary (7) field write error: ", p), err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 7:vBinary: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Tag) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("Tag(%+v)", *p)
-}
-
-// Attributes:
-//  - Timestamp
-//  - Fields
-type Log struct {
-	Timestamp int64  `thrift:"timestamp,1,required" db:"timestamp" json:"timestamp"`
-	Fields    []*Tag `thrift:"fields,2,required" db:"fields" json:"fields"`
-}
-
-func NewLog() *Log {
-	return &Log{}
-}
-
-func (p *Log) GetTimestamp() int64 {
-	return p.Timestamp
-}
-
-func (p *Log) GetFields() []*Tag {
-	return p.Fields
-}
-func (p *Log) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	var issetTimestamp bool = false
-	var issetFields bool = false
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField1(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetTimestamp = true
-		case 2:
-			if fieldTypeId == thrift.LIST {
-				if err := p.ReadField2(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetFields = true
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	if !issetTimestamp {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Timestamp is not set"))
-	}
-	if !issetFields {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Fields is not set"))
-	}
-	return nil
-}
-
-func (p *Log) ReadField1(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 1: ", err)
-	} else {
-		p.Timestamp = v
-	}
-	return nil
-}
-
-func (p *Log) ReadField2(iprot thrift.TProtocol) error {
-	_, size, err := iprot.ReadListBegin()
-	if err != nil {
-		return thrift.PrependError("error reading list begin: ", err)
-	}
-	tSlice := make([]*Tag, 0, size)
-	p.Fields = tSlice
-	for i := 0; i < size; i++ {
-		_elem0 := &Tag{}
-		if err := _elem0.Read(iprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem0), err)
-		}
-		p.Fields = append(p.Fields, _elem0)
-	}
-	if err := iprot.ReadListEnd(); err != nil {
-		return thrift.PrependError("error reading list end: ", err)
-	}
-	return nil
-}
-
-func (p *Log) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("Log"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField1(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField2(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *Log) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("timestamp", thrift.I64, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:timestamp: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.Timestamp)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.timestamp (1) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:timestamp: ", p), err)
-	}
-	return err
-}
-
-func (p *Log) writeField2(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("fields", thrift.LIST, 2); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:fields: ", p), err)
-	}
-	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Fields)); err != nil {
-		return thrift.PrependError("error writing list begin: ", err)
-	}
-	for _, v := range p.Fields {
-		if err := v.Write(oprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
-		}
-	}
-	if err := oprot.WriteListEnd(); err != nil {
-		return thrift.PrependError("error writing list end: ", err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:fields: ", p), err)
-	}
-	return err
-}
-
-func (p *Log) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("Log(%+v)", *p)
-}
-
-// Attributes:
-//  - RefType
-//  - TraceIdLow
-//  - TraceIdHigh
-//  - SpanId
-type SpanRef struct {
-	RefType     SpanRefType `thrift:"refType,1,required" db:"refType" json:"refType"`
-	TraceIdLow  int64       `thrift:"traceIdLow,2,required" db:"traceIdLow" json:"traceIdLow"`
-	TraceIdHigh int64       `thrift:"traceIdHigh,3,required" db:"traceIdHigh" json:"traceIdHigh"`
-	SpanId      int64       `thrift:"spanId,4,required" db:"spanId" json:"spanId"`
-}
-
-func NewSpanRef() *SpanRef {
-	return &SpanRef{}
-}
-
-func (p *SpanRef) GetRefType() SpanRefType {
-	return p.RefType
-}
-
-func (p *SpanRef) GetTraceIdLow() int64 {
-	return p.TraceIdLow
-}
-
-func (p *SpanRef) GetTraceIdHigh() int64 {
-	return p.TraceIdHigh
-}
-
-func (p *SpanRef) GetSpanId() int64 {
-	return p.SpanId
-}
-func (p *SpanRef) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	var issetRefType bool = false
-	var issetTraceIdLow bool = false
-	var issetTraceIdHigh bool = false
-	var issetSpanId bool = false
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if fieldTypeId == thrift.I32 {
-				if err := p.ReadField1(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetRefType = true
-		case 2:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField2(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetTraceIdLow = true
-		case 3:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField3(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetTraceIdHigh = true
-		case 4:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField4(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetSpanId = true
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	if !issetRefType {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field RefType is not set"))
-	}
-	if !issetTraceIdLow {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdLow is not set"))
-	}
-	if !issetTraceIdHigh {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdHigh is not set"))
-	}
-	if !issetSpanId {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field SpanId is not set"))
-	}
-	return nil
-}
-
-func (p *SpanRef) ReadField1(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI32(); err != nil {
-		return thrift.PrependError("error reading field 1: ", err)
-	} else {
-		temp := SpanRefType(v)
-		p.RefType = temp
-	}
-	return nil
-}
-
-func (p *SpanRef) ReadField2(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 2: ", err)
-	} else {
-		p.TraceIdLow = v
-	}
-	return nil
-}
-
-func (p *SpanRef) ReadField3(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 3: ", err)
-	} else {
-		p.TraceIdHigh = v
-	}
-	return nil
-}
-
-func (p *SpanRef) ReadField4(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 4: ", err)
-	} else {
-		p.SpanId = v
-	}
-	return nil
-}
-
-func (p *SpanRef) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("SpanRef"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField1(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField2(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField3(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField4(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *SpanRef) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("refType", thrift.I32, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:refType: ", p), err)
-	}
-	if err := oprot.WriteI32(int32(p.RefType)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.refType (1) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:refType: ", p), err)
-	}
-	return err
-}
-
-func (p *SpanRef) writeField2(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("traceIdLow", thrift.I64, 2); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:traceIdLow: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.TraceIdLow)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.traceIdLow (2) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:traceIdLow: ", p), err)
-	}
-	return err
-}
-
-func (p *SpanRef) writeField3(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("traceIdHigh", thrift.I64, 3); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:traceIdHigh: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.TraceIdHigh)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.traceIdHigh (3) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:traceIdHigh: ", p), err)
-	}
-	return err
-}
-
-func (p *SpanRef) writeField4(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("spanId", thrift.I64, 4); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:spanId: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.SpanId)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.spanId (4) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 4:spanId: ", p), err)
-	}
-	return err
-}
-
-func (p *SpanRef) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("SpanRef(%+v)", *p)
-}
-
-// Attributes:
-//  - TraceIdLow
-//  - TraceIdHigh
-//  - SpanId
-//  - ParentSpanId
-//  - OperationName
-//  - References
-//  - Flags
-//  - StartTime
-//  - Duration
-//  - Tags
-//  - Logs
-type Span struct {
-	TraceIdLow    int64      `thrift:"traceIdLow,1,required" db:"traceIdLow" json:"traceIdLow"`
-	TraceIdHigh   int64      `thrift:"traceIdHigh,2,required" db:"traceIdHigh" json:"traceIdHigh"`
-	SpanId        int64      `thrift:"spanId,3,required" db:"spanId" json:"spanId"`
-	ParentSpanId  int64      `thrift:"parentSpanId,4,required" db:"parentSpanId" json:"parentSpanId"`
-	OperationName string     `thrift:"operationName,5,required" db:"operationName" json:"operationName"`
-	References    []*SpanRef `thrift:"references,6" db:"references" json:"references,omitempty"`
-	Flags         int32      `thrift:"flags,7,required" db:"flags" json:"flags"`
-	StartTime     int64      `thrift:"startTime,8,required" db:"startTime" json:"startTime"`
-	Duration      int64      `thrift:"duration,9,required" db:"duration" json:"duration"`
-	Tags          []*Tag     `thrift:"tags,10" db:"tags" json:"tags,omitempty"`
-	Logs          []*Log     `thrift:"logs,11" db:"logs" json:"logs,omitempty"`
-}
-
-func NewSpan() *Span {
-	return &Span{}
-}
-
-func (p *Span) GetTraceIdLow() int64 {
-	return p.TraceIdLow
-}
-
-func (p *Span) GetTraceIdHigh() int64 {
-	return p.TraceIdHigh
-}
-
-func (p *Span) GetSpanId() int64 {
-	return p.SpanId
-}
-
-func (p *Span) GetParentSpanId() int64 {
-	return p.ParentSpanId
-}
-
-func (p *Span) GetOperationName() string {
-	return p.OperationName
-}
-
-var Span_References_DEFAULT []*SpanRef
-
-func (p *Span) GetReferences() []*SpanRef {
-	return p.References
-}
-
-func (p *Span) GetFlags() int32 {
-	return p.Flags
-}
-
-func (p *Span) GetStartTime() int64 {
-	return p.StartTime
-}
-
-func (p *Span) GetDuration() int64 {
-	return p.Duration
-}
-
-var Span_Tags_DEFAULT []*Tag
-
-func (p *Span) GetTags() []*Tag {
-	return p.Tags
-}
-
-var Span_Logs_DEFAULT []*Log
-
-func (p *Span) GetLogs() []*Log {
-	return p.Logs
-}
-func (p *Span) IsSetReferences() bool {
-	return p.References != nil
-}
-
-func (p *Span) IsSetTags() bool {
-	return p.Tags != nil
-}
-
-func (p *Span) IsSetLogs() bool {
-	return p.Logs != nil
-}
-
-func (p *Span) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	var issetTraceIdLow bool = false
-	var issetTraceIdHigh bool = false
-	var issetSpanId bool = false
-	var issetParentSpanId bool = false
-	var issetOperationName bool = false
-	var issetFlags bool = false
-	var issetStartTime bool = false
-	var issetDuration bool = false
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField1(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetTraceIdLow = true
-		case 2:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField2(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetTraceIdHigh = true
-		case 3:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField3(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetSpanId = true
-		case 4:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField4(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetParentSpanId = true
-		case 5:
-			if fieldTypeId == thrift.STRING {
-				if err := p.ReadField5(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetOperationName = true
-		case 6:
-			if fieldTypeId == thrift.LIST {
-				if err := p.ReadField6(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		case 7:
-			if fieldTypeId == thrift.I32 {
-				if err := p.ReadField7(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetFlags = true
-		case 8:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField8(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetStartTime = true
-		case 9:
-			if fieldTypeId == thrift.I64 {
-				if err := p.ReadField9(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetDuration = true
-		case 10:
-			if fieldTypeId == thrift.LIST {
-				if err := p.ReadField10(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		case 11:
-			if fieldTypeId == thrift.LIST {
-				if err := p.ReadField11(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	if !issetTraceIdLow {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdLow is not set"))
-	}
-	if !issetTraceIdHigh {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field TraceIdHigh is not set"))
-	}
-	if !issetSpanId {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field SpanId is not set"))
-	}
-	if !issetParentSpanId {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field ParentSpanId is not set"))
-	}
-	if !issetOperationName {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field OperationName is not set"))
-	}
-	if !issetFlags {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Flags is not set"))
-	}
-	if !issetStartTime {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field StartTime is not set"))
-	}
-	if !issetDuration {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Duration is not set"))
-	}
-	return nil
-}
-
-func (p *Span) ReadField1(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 1: ", err)
-	} else {
-		p.TraceIdLow = v
-	}
-	return nil
-}
-
-func (p *Span) ReadField2(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 2: ", err)
-	} else {
-		p.TraceIdHigh = v
-	}
-	return nil
-}
-
-func (p *Span) ReadField3(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 3: ", err)
-	} else {
-		p.SpanId = v
-	}
-	return nil
-}
-
-func (p *Span) ReadField4(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 4: ", err)
-	} else {
-		p.ParentSpanId = v
-	}
-	return nil
-}
-
-func (p *Span) ReadField5(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadString(); err != nil {
-		return thrift.PrependError("error reading field 5: ", err)
-	} else {
-		p.OperationName = v
-	}
-	return nil
-}
-
-func (p *Span) ReadField6(iprot thrift.TProtocol) error {
-	_, size, err := iprot.ReadListBegin()
-	if err != nil {
-		return thrift.PrependError("error reading list begin: ", err)
-	}
-	tSlice := make([]*SpanRef, 0, size)
-	p.References = tSlice
-	for i := 0; i < size; i++ {
-		_elem1 := &SpanRef{}
-		if err := _elem1.Read(iprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem1), err)
-		}
-		p.References = append(p.References, _elem1)
-	}
-	if err := iprot.ReadListEnd(); err != nil {
-		return thrift.PrependError("error reading list end: ", err)
-	}
-	return nil
-}
-
-func (p *Span) ReadField7(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI32(); err != nil {
-		return thrift.PrependError("error reading field 7: ", err)
-	} else {
-		p.Flags = v
-	}
-	return nil
-}
-
-func (p *Span) ReadField8(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 8: ", err)
-	} else {
-		p.StartTime = v
-	}
-	return nil
-}
-
-func (p *Span) ReadField9(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadI64(); err != nil {
-		return thrift.PrependError("error reading field 9: ", err)
-	} else {
-		p.Duration = v
-	}
-	return nil
-}
-
-func (p *Span) ReadField10(iprot thrift.TProtocol) error {
-	_, size, err := iprot.ReadListBegin()
-	if err != nil {
-		return thrift.PrependError("error reading list begin: ", err)
-	}
-	tSlice := make([]*Tag, 0, size)
-	p.Tags = tSlice
-	for i := 0; i < size; i++ {
-		_elem2 := &Tag{}
-		if err := _elem2.Read(iprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem2), err)
-		}
-		p.Tags = append(p.Tags, _elem2)
-	}
-	if err := iprot.ReadListEnd(); err != nil {
-		return thrift.PrependError("error reading list end: ", err)
-	}
-	return nil
-}
-
-func (p *Span) ReadField11(iprot thrift.TProtocol) error {
-	_, size, err := iprot.ReadListBegin()
-	if err != nil {
-		return thrift.PrependError("error reading list begin: ", err)
-	}
-	tSlice := make([]*Log, 0, size)
-	p.Logs = tSlice
-	for i := 0; i < size; i++ {
-		_elem3 := &Log{}
-		if err := _elem3.Read(iprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem3), err)
-		}
-		p.Logs = append(p.Logs, _elem3)
-	}
-	if err := iprot.ReadListEnd(); err != nil {
-		return thrift.PrependError("error reading list end: ", err)
-	}
-	return nil
-}
-
-func (p *Span) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("Span"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField1(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField2(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField3(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField4(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField5(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField6(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField7(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField8(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField9(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField10(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField11(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *Span) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("traceIdLow", thrift.I64, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:traceIdLow: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.TraceIdLow)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.traceIdLow (1) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:traceIdLow: ", p), err)
-	}
-	return err
-}
-
-func (p *Span) writeField2(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("traceIdHigh", thrift.I64, 2); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:traceIdHigh: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.TraceIdHigh)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.traceIdHigh (2) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:traceIdHigh: ", p), err)
-	}
-	return err
-}
-
-func (p *Span) writeField3(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("spanId", thrift.I64, 3); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 3:spanId: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.SpanId)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.spanId (3) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 3:spanId: ", p), err)
-	}
-	return err
-}
-
-func (p *Span) writeField4(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("parentSpanId", thrift.I64, 4); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 4:parentSpanId: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.ParentSpanId)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.parentSpanId (4) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 4:parentSpanId: ", p), err)
-	}
-	return err
-}
-
-func (p *Span) writeField5(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("operationName", thrift.STRING, 5); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 5:operationName: ", p), err)
-	}
-	if err := oprot.WriteString(string(p.OperationName)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.operationName (5) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 5:operationName: ", p), err)
-	}
-	return err
-}
-
-func (p *Span) writeField6(oprot thrift.TProtocol) (err error) {
-	if p.IsSetReferences() {
-		if err := oprot.WriteFieldBegin("references", thrift.LIST, 6); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 6:references: ", p), err)
-		}
-		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.References)); err != nil {
-			return thrift.PrependError("error writing list begin: ", err)
-		}
-		for _, v := range p.References {
-			if err := v.Write(oprot); err != nil {
-				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
-			}
-		}
-		if err := oprot.WriteListEnd(); err != nil {
-			return thrift.PrependError("error writing list end: ", err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 6:references: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Span) writeField7(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("flags", thrift.I32, 7); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 7:flags: ", p), err)
-	}
-	if err := oprot.WriteI32(int32(p.Flags)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.flags (7) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 7:flags: ", p), err)
-	}
-	return err
-}
-
-func (p *Span) writeField8(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("startTime", thrift.I64, 8); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 8:startTime: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.StartTime)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.startTime (8) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 8:startTime: ", p), err)
-	}
-	return err
-}
-
-func (p *Span) writeField9(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("duration", thrift.I64, 9); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 9:duration: ", p), err)
-	}
-	if err := oprot.WriteI64(int64(p.Duration)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.duration (9) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 9:duration: ", p), err)
-	}
-	return err
-}
-
-func (p *Span) writeField10(oprot thrift.TProtocol) (err error) {
-	if p.IsSetTags() {
-		if err := oprot.WriteFieldBegin("tags", thrift.LIST, 10); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 10:tags: ", p), err)
-		}
-		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Tags)); err != nil {
-			return thrift.PrependError("error writing list begin: ", err)
-		}
-		for _, v := range p.Tags {
-			if err := v.Write(oprot); err != nil {
-				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
-			}
-		}
-		if err := oprot.WriteListEnd(); err != nil {
-			return thrift.PrependError("error writing list end: ", err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 10:tags: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Span) writeField11(oprot thrift.TProtocol) (err error) {
-	if p.IsSetLogs() {
-		if err := oprot.WriteFieldBegin("logs", thrift.LIST, 11); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 11:logs: ", p), err)
-		}
-		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Logs)); err != nil {
-			return thrift.PrependError("error writing list begin: ", err)
-		}
-		for _, v := range p.Logs {
-			if err := v.Write(oprot); err != nil {
-				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
-			}
-		}
-		if err := oprot.WriteListEnd(); err != nil {
-			return thrift.PrependError("error writing list end: ", err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 11:logs: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Span) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("Span(%+v)", *p)
-}
-
-// Attributes:
-//  - ServiceName
-//  - Tags
-type Process struct {
-	ServiceName string `thrift:"serviceName,1,required" db:"serviceName" json:"serviceName"`
-	Tags        []*Tag `thrift:"tags,2" db:"tags" json:"tags,omitempty"`
-}
-
-func NewProcess() *Process {
-	return &Process{}
-}
-
-func (p *Process) GetServiceName() string {
-	return p.ServiceName
-}
-
-var Process_Tags_DEFAULT []*Tag
-
-func (p *Process) GetTags() []*Tag {
-	return p.Tags
-}
-func (p *Process) IsSetTags() bool {
-	return p.Tags != nil
-}
-
-func (p *Process) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	var issetServiceName bool = false
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if fieldTypeId == thrift.STRING {
-				if err := p.ReadField1(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetServiceName = true
-		case 2:
-			if fieldTypeId == thrift.LIST {
-				if err := p.ReadField2(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	if !issetServiceName {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field ServiceName is not set"))
-	}
-	return nil
-}
-
-func (p *Process) ReadField1(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadString(); err != nil {
-		return thrift.PrependError("error reading field 1: ", err)
-	} else {
-		p.ServiceName = v
-	}
-	return nil
-}
-
-func (p *Process) ReadField2(iprot thrift.TProtocol) error {
-	_, size, err := iprot.ReadListBegin()
-	if err != nil {
-		return thrift.PrependError("error reading list begin: ", err)
-	}
-	tSlice := make([]*Tag, 0, size)
-	p.Tags = tSlice
-	for i := 0; i < size; i++ {
-		_elem4 := &Tag{}
-		if err := _elem4.Read(iprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem4), err)
-		}
-		p.Tags = append(p.Tags, _elem4)
-	}
-	if err := iprot.ReadListEnd(); err != nil {
-		return thrift.PrependError("error reading list end: ", err)
-	}
-	return nil
-}
-
-func (p *Process) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("Process"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField1(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField2(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *Process) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("serviceName", thrift.STRING, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:serviceName: ", p), err)
-	}
-	if err := oprot.WriteString(string(p.ServiceName)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.serviceName (1) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:serviceName: ", p), err)
-	}
-	return err
-}
-
-func (p *Process) writeField2(oprot thrift.TProtocol) (err error) {
-	if p.IsSetTags() {
-		if err := oprot.WriteFieldBegin("tags", thrift.LIST, 2); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:tags: ", p), err)
-		}
-		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Tags)); err != nil {
-			return thrift.PrependError("error writing list begin: ", err)
-		}
-		for _, v := range p.Tags {
-			if err := v.Write(oprot); err != nil {
-				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
-			}
-		}
-		if err := oprot.WriteListEnd(); err != nil {
-			return thrift.PrependError("error writing list end: ", err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 2:tags: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *Process) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("Process(%+v)", *p)
-}
-
-// Attributes:
-//  - Process
-//  - Spans
-type Batch struct {
-	Process *Process `thrift:"process,1,required" db:"process" json:"process"`
-	Spans   []*Span  `thrift:"spans,2,required" db:"spans" json:"spans"`
-}
-
-func NewBatch() *Batch {
-	return &Batch{}
-}
-
-var Batch_Process_DEFAULT *Process
-
-func (p *Batch) GetProcess() *Process {
-	if !p.IsSetProcess() {
-		return Batch_Process_DEFAULT
-	}
-	return p.Process
-}
-
-func (p *Batch) GetSpans() []*Span {
-	return p.Spans
-}
-func (p *Batch) IsSetProcess() bool {
-	return p.Process != nil
-}
-
-func (p *Batch) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	var issetProcess bool = false
-	var issetSpans bool = false
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if fieldTypeId == thrift.STRUCT {
-				if err := p.ReadField1(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetProcess = true
-		case 2:
-			if fieldTypeId == thrift.LIST {
-				if err := p.ReadField2(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetSpans = true
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	if !issetProcess {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Process is not set"))
-	}
-	if !issetSpans {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Spans is not set"))
-	}
-	return nil
-}
-
-func (p *Batch) ReadField1(iprot thrift.TProtocol) error {
-	p.Process = &Process{}
-	if err := p.Process.Read(iprot); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Process), err)
-	}
-	return nil
-}
-
-func (p *Batch) ReadField2(iprot thrift.TProtocol) error {
-	_, size, err := iprot.ReadListBegin()
-	if err != nil {
-		return thrift.PrependError("error reading list begin: ", err)
-	}
-	tSlice := make([]*Span, 0, size)
-	p.Spans = tSlice
-	for i := 0; i < size; i++ {
-		_elem5 := &Span{}
-		if err := _elem5.Read(iprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem5), err)
-		}
-		p.Spans = append(p.Spans, _elem5)
-	}
-	if err := iprot.ReadListEnd(); err != nil {
-		return thrift.PrependError("error reading list end: ", err)
-	}
-	return nil
-}
-
-func (p *Batch) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("Batch"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField1(oprot); err != nil {
-			return err
-		}
-		if err := p.writeField2(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *Batch) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("process", thrift.STRUCT, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:process: ", p), err)
-	}
-	if err := p.Process.Write(oprot); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Process), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:process: ", p), err)
-	}
-	return err
-}
-
-func (p *Batch) writeField2(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("spans", thrift.LIST, 2); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:spans: ", p), err)
-	}
-	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Spans)); err != nil {
-		return thrift.PrependError("error writing list begin: ", err)
-	}
-	for _, v := range p.Spans {
-		if err := v.Write(oprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
-		}
-	}
-	if err := oprot.WriteListEnd(); err != nil {
-		return thrift.PrependError("error writing list end: ", err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 2:spans: ", p), err)
-	}
-	return err
-}
-
-func (p *Batch) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("Batch(%+v)", *p)
-}
-
-// Attributes:
-//  - Ok
-type BatchSubmitResponse struct {
-	Ok bool `thrift:"ok,1,required" db:"ok" json:"ok"`
-}
-
-func NewBatchSubmitResponse() *BatchSubmitResponse {
-	return &BatchSubmitResponse{}
-}
-
-func (p *BatchSubmitResponse) GetOk() bool {
-	return p.Ok
-}
-func (p *BatchSubmitResponse) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	var issetOk bool = false
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if fieldTypeId == thrift.BOOL {
-				if err := p.ReadField1(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-			issetOk = true
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	if !issetOk {
-		return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Ok is not set"))
-	}
-	return nil
-}
-
-func (p *BatchSubmitResponse) ReadField1(iprot thrift.TProtocol) error {
-	if v, err := iprot.ReadBool(); err != nil {
-		return thrift.PrependError("error reading field 1: ", err)
-	} else {
-		p.Ok = v
-	}
-	return nil
-}
-
-func (p *BatchSubmitResponse) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("BatchSubmitResponse"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField1(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *BatchSubmitResponse) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("ok", thrift.BOOL, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:ok: ", p), err)
-	}
-	if err := oprot.WriteBool(bool(p.Ok)); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T.ok (1) field write error: ", p), err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:ok: ", p), err)
-	}
-	return err
-}
-
-func (p *BatchSubmitResponse) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("BatchSubmitResponse(%+v)", *p)
-}
-
-type Collector interface {
-	// Parameters:
-	//  - Batches
-	SubmitBatches(ctx context.Context, batches []*Batch) (r []*BatchSubmitResponse, err error)
-}
-
-type CollectorClient struct {
-	c thrift.TClient
-}
-
-// Deprecated: Use NewCollector instead
-func NewCollectorClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *CollectorClient {
-	return &CollectorClient{
-		c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t)),
-	}
-}
-
-// Deprecated: Use NewCollector instead
-func NewCollectorClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *CollectorClient {
-	return &CollectorClient{
-		c: thrift.NewTStandardClient(iprot, oprot),
-	}
-}
-
-func NewCollectorClient(c thrift.TClient) *CollectorClient {
-	return &CollectorClient{
-		c: c,
-	}
-}
-
-// Parameters:
-//  - Batches
-func (p *CollectorClient) SubmitBatches(ctx context.Context, batches []*Batch) (r []*BatchSubmitResponse, err error) {
-	var _args6 CollectorSubmitBatchesArgs
-	_args6.Batches = batches
-	var _result7 CollectorSubmitBatchesResult
-	if err = p.c.Call(ctx, "submitBatches", &_args6, &_result7); err != nil {
-		return
-	}
-	return _result7.GetSuccess(), nil
-}
-
-type CollectorProcessor struct {
-	processorMap map[string]thrift.TProcessorFunction
-	handler      Collector
-}
-
-func (p *CollectorProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
-	p.processorMap[key] = processor
-}
-
-func (p *CollectorProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
-	processor, ok = p.processorMap[key]
-	return processor, ok
-}
-
-func (p *CollectorProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
-	return p.processorMap
-}
-
-func NewCollectorProcessor(handler Collector) *CollectorProcessor {
-
-	self8 := &CollectorProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
-	self8.processorMap["submitBatches"] = &collectorProcessorSubmitBatches{handler: handler}
-	return self8
-}
-
-func (p *CollectorProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
-	name, _, seqId, err := iprot.ReadMessageBegin()
-	if err != nil {
-		return false, err
-	}
-	if processor, ok := p.GetProcessorFunction(name); ok {
-		return processor.Process(ctx, seqId, iprot, oprot)
-	}
-	iprot.Skip(thrift.STRUCT)
-	iprot.ReadMessageEnd()
-	x9 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
-	oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
-	x9.Write(oprot)
-	oprot.WriteMessageEnd()
-	oprot.Flush(ctx)
-	return false, x9
-
-}
-
-type collectorProcessorSubmitBatches struct {
-	handler Collector
-}
-
-func (p *collectorProcessorSubmitBatches) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
-	args := CollectorSubmitBatchesArgs{}
-	if err = args.Read(iprot); err != nil {
-		iprot.ReadMessageEnd()
-		x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
-		oprot.WriteMessageBegin("submitBatches", thrift.EXCEPTION, seqId)
-		x.Write(oprot)
-		oprot.WriteMessageEnd()
-		oprot.Flush(ctx)
-		return false, err
-	}
-
-	iprot.ReadMessageEnd()
-	result := CollectorSubmitBatchesResult{}
-	var retval []*BatchSubmitResponse
-	var err2 error
-	if retval, err2 = p.handler.SubmitBatches(ctx, args.Batches); err2 != nil {
-		x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing submitBatches: "+err2.Error())
-		oprot.WriteMessageBegin("submitBatches", thrift.EXCEPTION, seqId)
-		x.Write(oprot)
-		oprot.WriteMessageEnd()
-		oprot.Flush(ctx)
-		return true, err2
-	} else {
-		result.Success = retval
-	}
-	if err2 = oprot.WriteMessageBegin("submitBatches", thrift.REPLY, seqId); err2 != nil {
-		err = err2
-	}
-	if err2 = result.Write(oprot); err == nil && err2 != nil {
-		err = err2
-	}
-	if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
-		err = err2
-	}
-	if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
-		err = err2
-	}
-	if err != nil {
-		return
-	}
-	return true, err
-}
-
-// HELPER FUNCTIONS AND STRUCTURES
-
-// Attributes:
-//  - Batches
-type CollectorSubmitBatchesArgs struct {
-	Batches []*Batch `thrift:"batches,1" db:"batches" json:"batches"`
-}
-
-func NewCollectorSubmitBatchesArgs() *CollectorSubmitBatchesArgs {
-	return &CollectorSubmitBatchesArgs{}
-}
-
-func (p *CollectorSubmitBatchesArgs) GetBatches() []*Batch {
-	return p.Batches
-}
-func (p *CollectorSubmitBatchesArgs) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 1:
-			if fieldTypeId == thrift.LIST {
-				if err := p.ReadField1(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	return nil
-}
-
-func (p *CollectorSubmitBatchesArgs) ReadField1(iprot thrift.TProtocol) error {
-	_, size, err := iprot.ReadListBegin()
-	if err != nil {
-		return thrift.PrependError("error reading list begin: ", err)
-	}
-	tSlice := make([]*Batch, 0, size)
-	p.Batches = tSlice
-	for i := 0; i < size; i++ {
-		_elem10 := &Batch{}
-		if err := _elem10.Read(iprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem10), err)
-		}
-		p.Batches = append(p.Batches, _elem10)
-	}
-	if err := iprot.ReadListEnd(); err != nil {
-		return thrift.PrependError("error reading list end: ", err)
-	}
-	return nil
-}
-
-func (p *CollectorSubmitBatchesArgs) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("submitBatches_args"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField1(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *CollectorSubmitBatchesArgs) writeField1(oprot thrift.TProtocol) (err error) {
-	if err := oprot.WriteFieldBegin("batches", thrift.LIST, 1); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:batches: ", p), err)
-	}
-	if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Batches)); err != nil {
-		return thrift.PrependError("error writing list begin: ", err)
-	}
-	for _, v := range p.Batches {
-		if err := v.Write(oprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
-		}
-	}
-	if err := oprot.WriteListEnd(); err != nil {
-		return thrift.PrependError("error writing list end: ", err)
-	}
-	if err := oprot.WriteFieldEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write field end error 1:batches: ", p), err)
-	}
-	return err
-}
-
-func (p *CollectorSubmitBatchesArgs) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("CollectorSubmitBatchesArgs(%+v)", *p)
-}
-
-// Attributes:
-//  - Success
-type CollectorSubmitBatchesResult struct {
-	Success []*BatchSubmitResponse `thrift:"success,0" db:"success" json:"success,omitempty"`
-}
-
-func NewCollectorSubmitBatchesResult() *CollectorSubmitBatchesResult {
-	return &CollectorSubmitBatchesResult{}
-}
-
-var CollectorSubmitBatchesResult_Success_DEFAULT []*BatchSubmitResponse
-
-func (p *CollectorSubmitBatchesResult) GetSuccess() []*BatchSubmitResponse {
-	return p.Success
-}
-func (p *CollectorSubmitBatchesResult) IsSetSuccess() bool {
-	return p.Success != nil
-}
-
-func (p *CollectorSubmitBatchesResult) Read(iprot thrift.TProtocol) error {
-	if _, err := iprot.ReadStructBegin(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
-	}
-
-	for {
-		_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
-		if err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
-		}
-		if fieldTypeId == thrift.STOP {
-			break
-		}
-		switch fieldId {
-		case 0:
-			if fieldTypeId == thrift.LIST {
-				if err := p.ReadField0(iprot); err != nil {
-					return err
-				}
-			} else {
-				if err := iprot.Skip(fieldTypeId); err != nil {
-					return err
-				}
-			}
-		default:
-			if err := iprot.Skip(fieldTypeId); err != nil {
-				return err
-			}
-		}
-		if err := iprot.ReadFieldEnd(); err != nil {
-			return err
-		}
-	}
-	if err := iprot.ReadStructEnd(); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
-	}
-	return nil
-}
-
-func (p *CollectorSubmitBatchesResult) ReadField0(iprot thrift.TProtocol) error {
-	_, size, err := iprot.ReadListBegin()
-	if err != nil {
-		return thrift.PrependError("error reading list begin: ", err)
-	}
-	tSlice := make([]*BatchSubmitResponse, 0, size)
-	p.Success = tSlice
-	for i := 0; i < size; i++ {
-		_elem11 := &BatchSubmitResponse{}
-		if err := _elem11.Read(iprot); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem11), err)
-		}
-		p.Success = append(p.Success, _elem11)
-	}
-	if err := iprot.ReadListEnd(); err != nil {
-		return thrift.PrependError("error reading list end: ", err)
-	}
-	return nil
-}
-
-func (p *CollectorSubmitBatchesResult) Write(oprot thrift.TProtocol) error {
-	if err := oprot.WriteStructBegin("submitBatches_result"); err != nil {
-		return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
-	}
-	if p != nil {
-		if err := p.writeField0(oprot); err != nil {
-			return err
-		}
-	}
-	if err := oprot.WriteFieldStop(); err != nil {
-		return thrift.PrependError("write field stop error: ", err)
-	}
-	if err := oprot.WriteStructEnd(); err != nil {
-		return thrift.PrependError("write struct stop error: ", err)
-	}
-	return nil
-}
-
-func (p *CollectorSubmitBatchesResult) writeField0(oprot thrift.TProtocol) (err error) {
-	if p.IsSetSuccess() {
-		if err := oprot.WriteFieldBegin("success", thrift.LIST, 0); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
-		}
-		if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Success)); err != nil {
-			return thrift.PrependError("error writing list begin: ", err)
-		}
-		for _, v := range p.Success {
-			if err := v.Write(oprot); err != nil {
-				return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
-			}
-		}
-		if err := oprot.WriteListEnd(); err != nil {
-			return thrift.PrependError("error writing list end: ", err)
-		}
-		if err := oprot.WriteFieldEnd(); err != nil {
-			return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
-		}
-	}
-	return err
-}
-
-func (p *CollectorSubmitBatchesResult) String() string {
-	if p == nil {
-		return "<nil>"
-	}
-	return fmt.Sprintf("CollectorSubmitBatchesResult(%+v)", *p)
-}
diff --git a/exporter/jaeger/jaeger.go b/exporter/jaeger/jaeger.go
deleted file mode 100644
index 3574a06..0000000
--- a/exporter/jaeger/jaeger.go
+++ /dev/null
@@ -1,369 +0,0 @@
-// Copyright 2018, 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.
-
-// Package jaeger contains an OpenCensus tracing exporter for Jaeger.
-package jaeger // import "go.opencensus.io/exporter/jaeger"
-
-import (
-	"bytes"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"log"
-	"net/http"
-
-	"github.com/apache/thrift/lib/go/thrift"
-	gen "go.opencensus.io/exporter/jaeger/internal/gen-go/jaeger"
-	"go.opencensus.io/trace"
-	"google.golang.org/api/support/bundler"
-)
-
-const defaultServiceName = "OpenCensus"
-
-// Options are the options to be used when initializing a Jaeger exporter.
-type Options struct {
-	// Endpoint is the Jaeger HTTP Thrift endpoint.
-	// For example, http://localhost:14268.
-	//
-	// Deprecated: Use CollectorEndpoint instead.
-	Endpoint string
-
-	// CollectorEndpoint is the full url to the Jaeger HTTP Thrift collector.
-	// For example, http://localhost:14268/api/traces
-	CollectorEndpoint string
-
-	// AgentEndpoint instructs exporter to send spans to jaeger-agent at this address.
-	// For example, localhost:6831.
-	AgentEndpoint string
-
-	// OnError is the hook to be called when there is
-	// an error occurred when uploading the stats data.
-	// If no custom hook is set, errors are logged.
-	// Optional.
-	OnError func(err error)
-
-	// Username to be used if basic auth is required.
-	// Optional.
-	Username string
-
-	// Password to be used if basic auth is required.
-	// Optional.
-	Password string
-
-	// ServiceName is the Jaeger service name.
-	// Deprecated: Specify Process instead.
-	ServiceName string
-
-	// Process contains the information about the exporting process.
-	Process Process
-
-	//BufferMaxCount defines the total number of traces that can be buffered in memory
-	BufferMaxCount int
-}
-
-// NewExporter returns a trace.Exporter implementation that exports
-// the collected spans to Jaeger.
-func NewExporter(o Options) (*Exporter, error) {
-	if o.Endpoint == "" && o.CollectorEndpoint == "" && o.AgentEndpoint == "" {
-		return nil, errors.New("missing endpoint for Jaeger exporter")
-	}
-
-	var endpoint string
-	var client *agentClientUDP
-	var err error
-	if o.Endpoint != "" {
-		endpoint = o.Endpoint + "/api/traces?format=jaeger.thrift"
-		log.Printf("Endpoint has been deprecated. Please use CollectorEndpoint instead.")
-	} else if o.CollectorEndpoint != "" {
-		endpoint = o.CollectorEndpoint
-	} else {
-		client, err = newAgentClientUDP(o.AgentEndpoint, udpPacketMaxLength)
-		if err != nil {
-			return nil, err
-		}
-	}
-	onError := func(err error) {
-		if o.OnError != nil {
-			o.OnError(err)
-			return
-		}
-		log.Printf("Error when uploading spans to Jaeger: %v", err)
-	}
-	service := o.Process.ServiceName
-	if service == "" && o.ServiceName != "" {
-		// fallback to old service name if specified
-		service = o.ServiceName
-	} else if service == "" {
-		service = defaultServiceName
-	}
-	tags := make([]*gen.Tag, len(o.Process.Tags))
-	for i, tag := range o.Process.Tags {
-		tags[i] = attributeToTag(tag.key, tag.value)
-	}
-	e := &Exporter{
-		endpoint:      endpoint,
-		agentEndpoint: o.AgentEndpoint,
-		client:        client,
-		username:      o.Username,
-		password:      o.Password,
-		process: &gen.Process{
-			ServiceName: service,
-			Tags:        tags,
-		},
-	}
-	bundler := bundler.NewBundler((*gen.Span)(nil), func(bundle interface{}) {
-		if err := e.upload(bundle.([]*gen.Span)); err != nil {
-			onError(err)
-		}
-	})
-
-	// Set BufferedByteLimit with the total number of spans that are permissible to be held in memory.
-	// This needs to be done since the size of messages is always set to 1. Failing to set this would allow
-	// 1G messages to be held in memory since that is the default value of BufferedByteLimit.
-	if o.BufferMaxCount != 0 {
-		bundler.BufferedByteLimit = o.BufferMaxCount
-	}
-
-	e.bundler = bundler
-	return e, nil
-}
-
-// Process contains the information exported to jaeger about the source
-// of the trace data.
-type Process struct {
-	// ServiceName is the Jaeger service name.
-	ServiceName string
-
-	// Tags are added to Jaeger Process exports
-	Tags []Tag
-}
-
-// Tag defines a key-value pair
-// It is limited to the possible conversions to *jaeger.Tag by attributeToTag
-type Tag struct {
-	key   string
-	value interface{}
-}
-
-// BoolTag creates a new tag of type bool, exported as jaeger.TagType_BOOL
-func BoolTag(key string, value bool) Tag {
-	return Tag{key, value}
-}
-
-// StringTag creates a new tag of type string, exported as jaeger.TagType_STRING
-func StringTag(key string, value string) Tag {
-	return Tag{key, value}
-}
-
-// Int64Tag creates a new tag of type int64, exported as jaeger.TagType_LONG
-func Int64Tag(key string, value int64) Tag {
-	return Tag{key, value}
-}
-
-// Exporter is an implementation of trace.Exporter that uploads spans to Jaeger.
-type Exporter struct {
-	endpoint      string
-	agentEndpoint string
-	process       *gen.Process
-	bundler       *bundler.Bundler
-	client        *agentClientUDP
-
-	username, password string
-}
-
-var _ trace.Exporter = (*Exporter)(nil)
-
-// ExportSpan exports a SpanData to Jaeger.
-func (e *Exporter) ExportSpan(data *trace.SpanData) {
-	e.bundler.Add(spanDataToThrift(data), 1)
-	// TODO(jbd): Handle oversized bundlers.
-}
-
-// As per the OpenCensus Status code mapping in
-//    https://opencensus.io/tracing/span/status/
-// the status is OK if the code is 0.
-const opencensusStatusCodeOK = 0
-
-func spanDataToThrift(data *trace.SpanData) *gen.Span {
-	tags := make([]*gen.Tag, 0, len(data.Attributes))
-	for k, v := range data.Attributes {
-		tag := attributeToTag(k, v)
-		if tag != nil {
-			tags = append(tags, tag)
-		}
-	}
-
-	tags = append(tags,
-		attributeToTag("status.code", data.Status.Code),
-		attributeToTag("status.message", data.Status.Message),
-	)
-
-	// Ensure that if Status.Code is not OK, that we set the "error" tag on the Jaeger span.
-	// See Issue https://github.com/census-instrumentation/opencensus-go/issues/1041
-	if data.Status.Code != opencensusStatusCodeOK {
-		tags = append(tags, attributeToTag("error", true))
-	}
-
-	var logs []*gen.Log
-	for _, a := range data.Annotations {
-		fields := make([]*gen.Tag, 0, len(a.Attributes))
-		for k, v := range a.Attributes {
-			tag := attributeToTag(k, v)
-			if tag != nil {
-				fields = append(fields, tag)
-			}
-		}
-		fields = append(fields, attributeToTag("message", a.Message))
-		logs = append(logs, &gen.Log{
-			Timestamp: a.Time.UnixNano() / 1000,
-			Fields:    fields,
-		})
-	}
-	var refs []*gen.SpanRef
-	for _, link := range data.Links {
-		refs = append(refs, &gen.SpanRef{
-			TraceIdHigh: bytesToInt64(link.TraceID[0:8]),
-			TraceIdLow:  bytesToInt64(link.TraceID[8:16]),
-			SpanId:      bytesToInt64(link.SpanID[:]),
-		})
-	}
-	return &gen.Span{
-		TraceIdHigh:   bytesToInt64(data.TraceID[0:8]),
-		TraceIdLow:    bytesToInt64(data.TraceID[8:16]),
-		SpanId:        bytesToInt64(data.SpanID[:]),
-		ParentSpanId:  bytesToInt64(data.ParentSpanID[:]),
-		OperationName: name(data),
-		Flags:         int32(data.TraceOptions),
-		StartTime:     data.StartTime.UnixNano() / 1000,
-		Duration:      data.EndTime.Sub(data.StartTime).Nanoseconds() / 1000,
-		Tags:          tags,
-		Logs:          logs,
-		References:    refs,
-	}
-}
-
-func name(sd *trace.SpanData) string {
-	n := sd.Name
-	switch sd.SpanKind {
-	case trace.SpanKindClient:
-		n = "Sent." + n
-	case trace.SpanKindServer:
-		n = "Recv." + n
-	}
-	return n
-}
-
-func attributeToTag(key string, a interface{}) *gen.Tag {
-	var tag *gen.Tag
-	switch value := a.(type) {
-	case bool:
-		tag = &gen.Tag{
-			Key:   key,
-			VBool: &value,
-			VType: gen.TagType_BOOL,
-		}
-	case string:
-		tag = &gen.Tag{
-			Key:   key,
-			VStr:  &value,
-			VType: gen.TagType_STRING,
-		}
-	case int64:
-		tag = &gen.Tag{
-			Key:   key,
-			VLong: &value,
-			VType: gen.TagType_LONG,
-		}
-	case int32:
-		v := int64(value)
-		tag = &gen.Tag{
-			Key:   key,
-			VLong: &v,
-			VType: gen.TagType_LONG,
-		}
-	case float64:
-		v := float64(value)
-		tag = &gen.Tag{
-			Key:     key,
-			VDouble: &v,
-			VType:   gen.TagType_DOUBLE,
-		}
-	}
-	return tag
-}
-
-// Flush waits for exported trace spans to be uploaded.
-//
-// This is useful if your program is ending and you do not want to lose recent spans.
-func (e *Exporter) Flush() {
-	e.bundler.Flush()
-}
-
-func (e *Exporter) upload(spans []*gen.Span) error {
-	batch := &gen.Batch{
-		Spans:   spans,
-		Process: e.process,
-	}
-	if e.endpoint != "" {
-		return e.uploadCollector(batch)
-	}
-	return e.uploadAgent(batch)
-}
-
-func (e *Exporter) uploadAgent(batch *gen.Batch) error {
-	return e.client.EmitBatch(batch)
-}
-
-func (e *Exporter) uploadCollector(batch *gen.Batch) error {
-	body, err := serialize(batch)
-	if err != nil {
-		return err
-	}
-	req, err := http.NewRequest("POST", e.endpoint, body)
-	if err != nil {
-		return err
-	}
-	if e.username != "" && e.password != "" {
-		req.SetBasicAuth(e.username, e.password)
-	}
-	req.Header.Set("Content-Type", "application/x-thrift")
-
-	resp, err := http.DefaultClient.Do(req)
-	if err != nil {
-		return err
-	}
-
-	io.Copy(ioutil.Discard, resp.Body)
-	resp.Body.Close()
-
-	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
-		return fmt.Errorf("failed to upload traces; HTTP status code: %d", resp.StatusCode)
-	}
-	return nil
-}
-
-func serialize(obj thrift.TStruct) (*bytes.Buffer, error) {
-	buf := thrift.NewTMemoryBuffer()
-	if err := obj.Write(thrift.NewTBinaryProtocolTransport(buf)); err != nil {
-		return nil, err
-	}
-	return buf.Buffer, nil
-}
-
-func bytesToInt64(buf []byte) int64 {
-	u := binary.BigEndian.Uint64(buf)
-	return int64(u)
-}
diff --git a/exporter/prometheus/example/main.go b/exporter/prometheus/example/main.go
deleted file mode 100644
index 838cf36..0000000
--- a/exporter/prometheus/example/main.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2017, 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.
-
-// Command prometheus is an example program that collects data for
-// video size. Collected data is exported to Prometheus.
-package main
-
-import (
-	"context"
-	"log"
-	"math/rand"
-	"net/http"
-	"time"
-
-	"go.opencensus.io/exporter/prometheus"
-	"go.opencensus.io/stats"
-	"go.opencensus.io/stats/view"
-)
-
-// Create measures. The program will record measures for the size of
-// processed videos and the number of videos marked as spam.
-var (
-	videoCount = stats.Int64("example.com/measures/video_count", "number of processed videos", stats.UnitDimensionless)
-	videoSize  = stats.Int64("example.com/measures/video_size", "size of processed video", stats.UnitBytes)
-)
-
-func main() {
-	ctx := context.Background()
-
-	exporter, err := prometheus.NewExporter(prometheus.Options{})
-	if err != nil {
-		log.Fatal(err)
-	}
-	view.RegisterExporter(exporter)
-
-	// Create view to see the number of processed videos cumulatively.
-	// Create view to see the amount of video processed
-	// Subscribe will allow view data to be exported.
-	// Once no longer needed, you can unsubscribe from the view.
-	if err = view.Register(
-		&view.View{
-			Name:        "video_count",
-			Description: "number of videos processed over time",
-			Measure:     videoCount,
-			Aggregation: view.Count(),
-		},
-		&view.View{
-			Name:        "video_size",
-			Description: "processed video size over time",
-			Measure:     videoSize,
-			Aggregation: view.Distribution(0, 1<<16, 1<<32),
-		},
-	); err != nil {
-		log.Fatalf("Cannot register the view: %v", err)
-	}
-
-	// Set reporting period to report data at every second.
-	view.SetReportingPeriod(1 * time.Second)
-
-	// Record some data points...
-	go func() {
-		for {
-			stats.Record(ctx, videoCount.M(1), videoSize.M(rand.Int63()))
-			<-time.After(time.Millisecond * time.Duration(1+rand.Intn(400)))
-		}
-	}()
-
-	addr := ":9999"
-	log.Printf("Serving at %s", addr)
-	http.Handle("/metrics", exporter)
-	log.Fatal(http.ListenAndServe(addr, nil))
-}
diff --git a/exporter/prometheus/prometheus.go b/exporter/prometheus/prometheus.go
deleted file mode 100644
index 9fbffb3..0000000
--- a/exporter/prometheus/prometheus.go
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright 2017, 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.
-
-// Package prometheus contains a Prometheus exporter that supports exporting
-// OpenCensus views as Prometheus metrics.
-package prometheus // import "go.opencensus.io/exporter/prometheus"
-
-import (
-	"fmt"
-	"log"
-	"net/http"
-	"sync"
-
-	"context"
-	"github.com/prometheus/client_golang/prometheus"
-	"github.com/prometheus/client_golang/prometheus/promhttp"
-	"go.opencensus.io/internal"
-	"go.opencensus.io/metric/metricdata"
-	"go.opencensus.io/metric/metricexport"
-	"go.opencensus.io/stats/view"
-)
-
-// Exporter exports stats to Prometheus, users need
-// to register the exporter as an http.Handler to be
-// able to export.
-type Exporter struct {
-	opts    Options
-	g       prometheus.Gatherer
-	c       *collector
-	handler http.Handler
-}
-
-// Options contains options for configuring the exporter.
-type Options struct {
-	Namespace   string
-	Registry    *prometheus.Registry
-	OnError     func(err error)
-	ConstLabels prometheus.Labels // ConstLabels will be set as labels on all views.
-}
-
-// NewExporter returns an exporter that exports stats to Prometheus.
-func NewExporter(o Options) (*Exporter, error) {
-	if o.Registry == nil {
-		o.Registry = prometheus.NewRegistry()
-	}
-	collector := newCollector(o, o.Registry)
-	e := &Exporter{
-		opts:    o,
-		g:       o.Registry,
-		c:       collector,
-		handler: promhttp.HandlerFor(o.Registry, promhttp.HandlerOpts{}),
-	}
-	collector.ensureRegisteredOnce()
-
-	return e, nil
-}
-
-var _ http.Handler = (*Exporter)(nil)
-
-// ensureRegisteredOnce invokes reg.Register on the collector itself
-// exactly once to ensure that we don't get errors such as
-//  cannot register the collector: descriptor Desc{fqName: *}
-//  already exists with the same fully-qualified name and const label values
-// which is documented by Prometheus at
-//  https://github.com/prometheus/client_golang/blob/fcc130e101e76c5d303513d0e28f4b6d732845c7/prometheus/registry.go#L89-L101
-func (c *collector) ensureRegisteredOnce() {
-	c.registerOnce.Do(func() {
-		if err := c.reg.Register(c); err != nil {
-			c.opts.onError(fmt.Errorf("cannot register the collector: %v", err))
-		}
-	})
-
-}
-
-func (o *Options) onError(err error) {
-	if o.OnError != nil {
-		o.OnError(err)
-	} else {
-		log.Printf("Failed to export to Prometheus: %v", err)
-	}
-}
-
-// ExportView exports to the Prometheus if view data has one or more rows.
-// Each OpenCensus AggregationData will be converted to
-// corresponding Prometheus Metric: SumData will be converted
-// to Untyped Metric, CountData will be a Counter Metric,
-// DistributionData will be a Histogram Metric.
-// Deprecated in lieu of metricexport.Reader interface.
-func (e *Exporter) ExportView(vd *view.Data) {
-}
-
-// ServeHTTP serves the Prometheus endpoint.
-func (e *Exporter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	e.handler.ServeHTTP(w, r)
-}
-
-// collector implements prometheus.Collector
-type collector struct {
-	opts Options
-	mu   sync.Mutex // mu guards all the fields.
-
-	registerOnce sync.Once
-
-	// reg helps collector register views dynamically.
-	reg *prometheus.Registry
-
-	// reader reads metrics from all registered producers.
-	reader *metricexport.Reader
-}
-
-func (c *collector) Describe(ch chan<- *prometheus.Desc) {
-	de := &descExporter{c: c, descCh: ch}
-	c.reader.ReadAndExport(de)
-}
-
-// Collect fetches the statistics from OpenCensus
-// and delivers them as Prometheus Metrics.
-// Collect is invoked every time a prometheus.Gatherer is run
-// for example when the HTTP endpoint is invoked by Prometheus.
-func (c *collector) Collect(ch chan<- prometheus.Metric) {
-	me := &metricExporter{c: c, metricCh: ch}
-	c.reader.ReadAndExport(me)
-}
-
-func newCollector(opts Options, registrar *prometheus.Registry) *collector {
-	return &collector{
-		reg:    registrar,
-		opts:   opts,
-		reader: metricexport.NewReader()}
-}
-
-func (c *collector) toDesc(metric *metricdata.Metric) *prometheus.Desc {
-	return prometheus.NewDesc(
-		metricName(c.opts.Namespace, metric),
-		metric.Descriptor.Description,
-		toPromLabels(metric.Descriptor.LabelKeys),
-		c.opts.ConstLabels)
-}
-
-type metricExporter struct {
-	c        *collector
-	metricCh chan<- prometheus.Metric
-}
-
-// ExportMetrics exports to the Prometheus.
-// Each OpenCensus Metric will be converted to
-// corresponding Prometheus Metric:
-// TypeCumulativeInt64 and TypeCumulativeFloat64 will be a Counter Metric,
-// TypeCumulativeDistribution will be a Histogram Metric.
-// TypeGaugeFloat64 and TypeGaugeInt64 will be a Gauge Metric
-func (me *metricExporter) ExportMetrics(ctx context.Context, metrics []*metricdata.Metric) error {
-	for _, metric := range metrics {
-		desc := me.c.toDesc(metric)
-		for _, ts := range metric.TimeSeries {
-			tvs := toLabelValues(ts.LabelValues)
-			for _, point := range ts.Points {
-				metric, err := toPromMetric(desc, metric, point, tvs)
-				if err != nil {
-					me.c.opts.onError(err)
-				} else if metric != nil {
-					me.metricCh <- metric
-				}
-			}
-		}
-	}
-	return nil
-}
-
-type descExporter struct {
-	c      *collector
-	descCh chan<- *prometheus.Desc
-}
-
-// ExportMetrics exports descriptor to the Prometheus.
-// It is invoked when request to scrape descriptors is received.
-func (me *descExporter) ExportMetrics(ctx context.Context, metrics []*metricdata.Metric) error {
-	for _, metric := range metrics {
-		desc := me.c.toDesc(metric)
-		me.descCh <- desc
-	}
-	return nil
-}
-
-func toPromLabels(mls []metricdata.LabelKey) (labels []string) {
-	for _, ml := range mls {
-		labels = append(labels, internal.Sanitize(ml.Key))
-	}
-	return labels
-}
-
-func metricName(namespace string, m *metricdata.Metric) string {
-	var name string
-	if namespace != "" {
-		name = namespace + "_"
-	}
-	return name + internal.Sanitize(m.Descriptor.Name)
-}
-
-func toPromMetric(
-	desc *prometheus.Desc,
-	metric *metricdata.Metric,
-	point metricdata.Point,
-	labelValues []string) (prometheus.Metric, error) {
-	switch metric.Descriptor.Type {
-	case metricdata.TypeCumulativeFloat64, metricdata.TypeCumulativeInt64:
-		pv, err := toPromValue(point)
-		if err != nil {
-			return nil, err
-		}
-		return prometheus.NewConstMetric(desc, prometheus.CounterValue, pv, labelValues...)
-
-	case metricdata.TypeGaugeFloat64, metricdata.TypeGaugeInt64:
-		pv, err := toPromValue(point)
-		if err != nil {
-			return nil, err
-		}
-		return prometheus.NewConstMetric(desc, prometheus.GaugeValue, pv, labelValues...)
-
-	case metricdata.TypeCumulativeDistribution:
-		switch v := point.Value.(type) {
-		case *metricdata.Distribution:
-			points := make(map[float64]uint64)
-			// Histograms are cumulative in Prometheus.
-			// Get cumulative bucket counts.
-			cumCount := uint64(0)
-			for i, b := range v.BucketOptions.Bounds {
-				cumCount += uint64(v.Buckets[i].Count)
-				points[b] = cumCount
-			}
-			return prometheus.NewConstHistogram(desc, uint64(v.Count), v.Sum, points, labelValues...)
-		default:
-			return nil, typeMismatchError(point)
-		}
-	case metricdata.TypeSummary:
-		// TODO: [rghetia] add support for TypeSummary.
-		return nil, nil
-	default:
-		return nil, fmt.Errorf("aggregation %T is not yet supported", metric.Descriptor.Type)
-	}
-}
-
-func toLabelValues(labelValues []metricdata.LabelValue) (values []string) {
-	for _, lv := range labelValues {
-		if lv.Present {
-			values = append(values, lv.Value)
-		} else {
-			values = append(values, "")
-		}
-	}
-	return values
-}
-
-func typeMismatchError(point metricdata.Point) error {
-	return fmt.Errorf("point type %T does not match metric type", point)
-
-}
-
-func toPromValue(point metricdata.Point) (float64, error) {
-	switch v := point.Value.(type) {
-	case float64:
-		return v, nil
-	case int64:
-		return float64(v), nil
-	default:
-		return 0.0, typeMismatchError(point)
-	}
-}
diff --git a/exporter/zipkin/example/main.go b/exporter/zipkin/example/main.go
deleted file mode 100644
index 9466c98..0000000
--- a/exporter/zipkin/example/main.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2018, 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.
-
-package main
-
-import (
-	"context"
-	"log"
-	"time"
-
-	openzipkin "github.com/openzipkin/zipkin-go"
-	"github.com/openzipkin/zipkin-go/reporter/http"
-	"go.opencensus.io/exporter/zipkin"
-	"go.opencensus.io/trace"
-)
-
-func main() {
-	// The localEndpoint stores the name and address of the local service
-	localEndpoint, err := openzipkin.NewEndpoint("example-server", "192.168.1.5:5454")
-	if err != nil {
-		log.Println(err)
-	}
-
-	// The Zipkin reporter takes collected spans from the app and reports them to the backend
-	// http://localhost:9411/api/v2/spans is the default for the Zipkin Span v2
-	reporter := http.NewReporter("http://localhost:9411/api/v2/spans")
-	defer reporter.Close()
-
-	// The OpenCensus exporter wraps the Zipkin reporter
-	exporter := zipkin.NewExporter(reporter, localEndpoint)
-	trace.RegisterExporter(exporter)
-
-	// For example purposes, sample every trace. In a production application, you should
-	// configure this to a trace.ProbabilitySampler set at the desired
-	// probability.
-	trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
-
-	ctx := context.Background()
-	foo(ctx)
-}
-
-func foo(ctx context.Context) {
-	// Name the current span "/foo"
-	ctx, span := trace.StartSpan(ctx, "/foo")
-	defer span.End()
-
-	// Foo calls bar and baz
-	bar(ctx)
-	baz(ctx)
-}
-
-func bar(ctx context.Context) {
-	ctx, span := trace.StartSpan(ctx, "/bar")
-	defer span.End()
-
-	// Do bar
-	time.Sleep(2 * time.Millisecond)
-}
-
-func baz(ctx context.Context) {
-	ctx, span := trace.StartSpan(ctx, "/baz")
-	defer span.End()
-
-	// Do baz
-	time.Sleep(4 * time.Millisecond)
-}
diff --git a/exporter/zipkin/zipkin.go b/exporter/zipkin/zipkin.go
deleted file mode 100644
index 69de705..0000000
--- a/exporter/zipkin/zipkin.go
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2017, 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.
-
-// Package zipkin contains an trace exporter for Zipkin.
-package zipkin // import "go.opencensus.io/exporter/zipkin"
-
-import (
-	"encoding/binary"
-	"strconv"
-
-	"github.com/openzipkin/zipkin-go/model"
-	"github.com/openzipkin/zipkin-go/reporter"
-	"go.opencensus.io/trace"
-)
-
-// Exporter is an implementation of trace.Exporter that uploads spans to a
-// Zipkin server.
-type Exporter struct {
-	reporter      reporter.Reporter
-	localEndpoint *model.Endpoint
-}
-
-// NewExporter returns an implementation of trace.Exporter that uploads spans
-// to a Zipkin server.
-//
-// reporter is a Zipkin Reporter which will be used to send the spans.  These
-// can be created with the openzipkin library, using one of the packages under
-// github.com/openzipkin/zipkin-go/reporter.
-//
-// localEndpoint sets the local endpoint of exported spans.  It can be
-// constructed with github.com/openzipkin/zipkin-go.NewEndpoint, e.g.:
-// 	localEndpoint, err := NewEndpoint("my server", listener.Addr().String())
-// localEndpoint can be nil.
-func NewExporter(reporter reporter.Reporter, localEndpoint *model.Endpoint) *Exporter {
-	return &Exporter{
-		reporter:      reporter,
-		localEndpoint: localEndpoint,
-	}
-}
-
-// ExportSpan exports a span to a Zipkin server.
-func (e *Exporter) ExportSpan(s *trace.SpanData) {
-	e.reporter.Send(zipkinSpan(s, e.localEndpoint))
-}
-
-const (
-	statusCodeTagKey        = "error"
-	statusDescriptionTagKey = "opencensus.status_description"
-)
-
-var (
-	sampledTrue    = true
-	canonicalCodes = [...]string{
-		"OK",
-		"CANCELLED",
-		"UNKNOWN",
-		"INVALID_ARGUMENT",
-		"DEADLINE_EXCEEDED",
-		"NOT_FOUND",
-		"ALREADY_EXISTS",
-		"PERMISSION_DENIED",
-		"RESOURCE_EXHAUSTED",
-		"FAILED_PRECONDITION",
-		"ABORTED",
-		"OUT_OF_RANGE",
-		"UNIMPLEMENTED",
-		"INTERNAL",
-		"UNAVAILABLE",
-		"DATA_LOSS",
-		"UNAUTHENTICATED",
-	}
-)
-
-func canonicalCodeString(code int32) string {
-	if code < 0 || int(code) >= len(canonicalCodes) {
-		return "error code " + strconv.FormatInt(int64(code), 10)
-	}
-	return canonicalCodes[code]
-}
-
-func convertTraceID(t trace.TraceID) model.TraceID {
-	return model.TraceID{
-		High: binary.BigEndian.Uint64(t[:8]),
-		Low:  binary.BigEndian.Uint64(t[8:]),
-	}
-}
-
-func convertSpanID(s trace.SpanID) model.ID {
-	return model.ID(binary.BigEndian.Uint64(s[:]))
-}
-
-func spanKind(s *trace.SpanData) model.Kind {
-	switch s.SpanKind {
-	case trace.SpanKindClient:
-		return model.Client
-	case trace.SpanKindServer:
-		return model.Server
-	}
-	return model.Undetermined
-}
-
-func zipkinSpan(s *trace.SpanData, localEndpoint *model.Endpoint) model.SpanModel {
-	sc := s.SpanContext
-	z := model.SpanModel{
-		SpanContext: model.SpanContext{
-			TraceID: convertTraceID(sc.TraceID),
-			ID:      convertSpanID(sc.SpanID),
-			Sampled: &sampledTrue,
-		},
-		Kind:          spanKind(s),
-		Name:          s.Name,
-		Timestamp:     s.StartTime,
-		Shared:        false,
-		LocalEndpoint: localEndpoint,
-	}
-
-	if s.ParentSpanID != (trace.SpanID{}) {
-		id := convertSpanID(s.ParentSpanID)
-		z.ParentID = &id
-	}
-
-	if s, e := s.StartTime, s.EndTime; !s.IsZero() && !e.IsZero() {
-		z.Duration = e.Sub(s)
-	}
-
-	// construct Tags from s.Attributes and s.Status.
-	if len(s.Attributes) != 0 {
-		m := make(map[string]string, len(s.Attributes)+2)
-		for key, value := range s.Attributes {
-			switch v := value.(type) {
-			case string:
-				m[key] = v
-			case bool:
-				if v {
-					m[key] = "true"
-				} else {
-					m[key] = "false"
-				}
-			case int64:
-				m[key] = strconv.FormatInt(v, 10)
-			case float64:
-				m[key] = strconv.FormatFloat(v, 'f', -1, 64)
-			}
-		}
-		z.Tags = m
-	}
-	if s.Status.Code != 0 || s.Status.Message != "" {
-		if z.Tags == nil {
-			z.Tags = make(map[string]string, 2)
-		}
-		if s.Status.Code != 0 {
-			z.Tags[statusCodeTagKey] = canonicalCodeString(s.Status.Code)
-		}
-		if s.Status.Message != "" {
-			z.Tags[statusDescriptionTagKey] = s.Status.Message
-		}
-	}
-
-	// construct Annotations from s.Annotations and s.MessageEvents.
-	if len(s.Annotations) != 0 || len(s.MessageEvents) != 0 {
-		z.Annotations = make([]model.Annotation, 0, len(s.Annotations)+len(s.MessageEvents))
-		for _, a := range s.Annotations {
-			z.Annotations = append(z.Annotations, model.Annotation{
-				Timestamp: a.Time,
-				Value:     a.Message,
-			})
-		}
-		for _, m := range s.MessageEvents {
-			a := model.Annotation{
-				Timestamp: m.Time,
-			}
-			switch m.EventType {
-			case trace.MessageEventTypeSent:
-				a.Value = "SENT"
-			case trace.MessageEventTypeRecv:
-				a.Value = "RECV"
-			default:
-				a.Value = "<?>"
-			}
-			z.Annotations = append(z.Annotations, a)
-		}
-	}
-
-	return z
-}
diff --git a/go.mod b/go.mod
index b59bf6c..8b7d38e 100644
--- a/go.mod
+++ b/go.mod
@@ -1,13 +1,10 @@
 module go.opencensus.io
 
 require (
-	github.com/apache/thrift v0.12.0
 	github.com/golang/protobuf v1.2.0
 	github.com/google/go-cmp v0.2.0
 	github.com/hashicorp/golang-lru v0.5.0
-	github.com/openzipkin/zipkin-go v0.1.6
-	github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829
 	golang.org/x/net v0.0.0-20190311183353-d8887717615a
-	google.golang.org/api v0.2.0
+	google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 // indirect
 	google.golang.org/grpc v1.19.0
 )
diff --git a/go.sum b/go.sum
index 300602f..32f144c 100644
--- a/go.sum
+++ b/go.sum
@@ -1,150 +1,44 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
-github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
-github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
-github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
-github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
-github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
-github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
-github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
-github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
-github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
-github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
-github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
 github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
-github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
-github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/openzipkin/zipkin-go v0.1.3 h1:36hTtUTQR/vPX7YVJo2PYexSbHdAJiAkDrjuXw/YlYQ=
-github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
-github.com/openzipkin/zipkin-go v0.1.6 h1:yXiysv1CSK7Q5yjGy1710zZGnsbMUIjluWBxtLXHPBo=
-github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
-github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
-github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA=
-github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
-github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
-github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
-github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
-github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
-github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
-github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A=
-golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY=
-golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181218192612-074acd46bca6 h1:MXtOG7w2ND9qNCUZSDBGll/SpVIq7ftozR9I8/JGBHY=
-golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-google.golang.org/api v0.0.0-20181220000619-583d854617af h1:iQMS7JKv/0w/iiWf1M49Cg3dmOkBoBZT5KheqPDpaac=
-google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
-google.golang.org/api v0.2.0 h1:B5VXkdjt7K2Gm6fGBC9C9a1OAKJDT95cTqwet+2zib0=
-google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb h1:dQshZyyJ5W/Xk8myF4GKBak1pZW6EywJuQ8+44EQhGA=
-google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
-google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
-gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
-gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/metric/common.go b/metric/common.go
index f5716c9..bd6e771 100644
--- a/metric/common.go
+++ b/metric/common.go
@@ -19,6 +19,7 @@ import (
 	"time"
 
 	"go.opencensus.io/internal/tagencoding"
+
 	"go.opencensus.io/metric/metricdata"
 )
 
@@ -30,11 +31,12 @@ import (
 // baseMetric should not be used directly, use metric specific type such as
 // Float64Gauge or Int64Gauge.
 type baseMetric struct {
-	vals   sync.Map
-	desc   metricdata.Descriptor
-	start  time.Time
-	keys   []metricdata.LabelKey
-	bmType baseMetricType
+	vals             sync.Map
+	desc             metricdata.Descriptor
+	start            time.Time
+	keys             []metricdata.LabelKey
+	constLabelValues []metricdata.LabelValue
+	bmType           baseMetricType
 }
 
 type baseMetricType int
@@ -118,6 +120,7 @@ func (bm *baseMetric) decodeLabelVals(s string) []metricdata.LabelValue {
 }
 
 func (bm *baseMetric) entryForValues(labelVals []metricdata.LabelValue, newEntry func() baseEntry) (interface{}, error) {
+	labelVals = append(bm.constLabelValues, labelVals...)
 	if len(labelVals) != len(bm.keys) {
 		return nil, errKeyValueMismatch
 	}
diff --git a/metric/registry.go b/metric/registry.go
index ceea7e9..6c58ff9 100644
--- a/metric/registry.go
+++ b/metric/registry.go
@@ -15,6 +15,7 @@
 package metric
 
 import (
+	"sort"
 	"sync"
 	"time"
 
@@ -28,11 +29,11 @@ type Registry struct {
 	baseMetrics sync.Map
 }
 
-//TODO: [rghetia] add constant labels.
 type metricOptions struct {
-	unit      metricdata.Unit
-	labelkeys []metricdata.LabelKey
-	desc      string
+	unit        metricdata.Unit
+	labelkeys   []metricdata.LabelKey
+	constLabels map[metricdata.LabelKey]metricdata.LabelValue
+	desc        string
 }
 
 // Options apply changes to metricOptions.
@@ -70,6 +71,13 @@ func WithLabelKeysAndDescription(labelKeys ...metricdata.LabelKey) Options {
 	}
 }
 
+// WithConstLabel applies provided constant label.
+func WithConstLabel(constLabels map[metricdata.LabelKey]metricdata.LabelValue) Options {
+	return func(mo *metricOptions) {
+		mo.constLabels = constLabels
+	}
+}
+
 // NewRegistry initializes a new Registry.
 func NewRegistry() *Registry {
 	return &Registry{}
@@ -236,12 +244,28 @@ func (r *Registry) initBaseMetric(bm *baseMetric, name string, mos ...Options) (
 	}
 	bm.start = time.Now()
 	o := createMetricOption(mos...)
-	bm.keys = o.labelkeys
+
+	var constLabelKeys []metricdata.LabelKey
+	for k := range o.constLabels {
+		constLabelKeys = append(constLabelKeys, k)
+	}
+	sort.Slice(constLabelKeys, func(i, j int) bool {
+		return constLabelKeys[i].Key < constLabelKeys[j].Key
+	})
+
+	var constLabelValues []metricdata.LabelValue
+	for _, k := range constLabelKeys {
+		constLabelValues = append(constLabelValues, o.constLabels[k])
+	}
+
+	bm.keys = append(constLabelKeys, o.labelkeys...)
+	bm.constLabelValues = constLabelValues
+
 	bm.desc = metricdata.Descriptor{
 		Name:        name,
 		Description: o.desc,
 		Unit:        o.unit,
-		LabelKeys:   o.labelkeys,
+		LabelKeys:   bm.keys,
 		Type:        bmTypeToMetricType(bm),
 	}
 	r.baseMetrics.Store(name, bm)
diff --git a/plugin/ocgrpc/stats_common.go b/plugin/ocgrpc/stats_common.go
index e9991fe..0ae5691 100644
--- a/plugin/ocgrpc/stats_common.go
+++ b/plugin/ocgrpc/stats_common.go
@@ -22,9 +22,11 @@ import (
 	"sync/atomic"
 	"time"
 
+	"go.opencensus.io/metric/metricdata"
 	ocstats "go.opencensus.io/stats"
 	"go.opencensus.io/stats/view"
 	"go.opencensus.io/tag"
+	"go.opencensus.io/trace"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/grpclog"
 	"google.golang.org/grpc/stats"
@@ -141,27 +143,31 @@ func handleRPCEnd(ctx context.Context, s *stats.End) {
 	}
 
 	latencyMillis := float64(elapsedTime) / float64(time.Millisecond)
+	attachments := getSpanCtxAttachment(ctx)
 	if s.Client {
-		ocstats.RecordWithTags(ctx,
-			[]tag.Mutator{
+		ocstats.RecordWithOptions(ctx,
+			ocstats.WithTags(
 				tag.Upsert(KeyClientMethod, methodName(d.method)),
-				tag.Upsert(KeyClientStatus, st),
-			},
-			ClientSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
-			ClientSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
-			ClientReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
-			ClientReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
-			ClientRoundtripLatency.M(latencyMillis))
+				tag.Upsert(KeyClientStatus, st)),
+			ocstats.WithAttachments(attachments),
+			ocstats.WithMeasurements(
+				ClientSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
+				ClientSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
+				ClientReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
+				ClientReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
+				ClientRoundtripLatency.M(latencyMillis)))
 	} else {
-		ocstats.RecordWithTags(ctx,
-			[]tag.Mutator{
+		ocstats.RecordWithOptions(ctx,
+			ocstats.WithTags(
 				tag.Upsert(KeyServerStatus, st),
-			},
-			ServerSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
-			ServerSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
-			ServerReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
-			ServerReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
-			ServerLatency.M(latencyMillis))
+			),
+			ocstats.WithAttachments(attachments),
+			ocstats.WithMeasurements(
+				ServerSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
+				ServerSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
+				ServerReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
+				ServerReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
+				ServerLatency.M(latencyMillis)))
 	}
 }
 
@@ -206,3 +212,16 @@ func statusCodeToString(s *status.Status) string {
 		return "CODE_" + strconv.FormatInt(int64(c), 10)
 	}
 }
+
+func getSpanCtxAttachment(ctx context.Context) metricdata.Attachments {
+	attachments := map[string]interface{}{}
+	span := trace.FromContext(ctx)
+	if span == nil {
+		return attachments
+	}
+	spanCtx := span.SpanContext()
+	if spanCtx.IsSampled() {
+		attachments[metricdata.AttachmentKeySpanContext] = spanCtx
+	}
+	return attachments
+}
diff --git a/plugin/ochttp/server.go b/plugin/ochttp/server.go
index 5fe15e8..4f6404f 100644
--- a/plugin/ochttp/server.go
+++ b/plugin/ochttp/server.go
@@ -124,6 +124,12 @@ func (h *Handler) startTrace(w http.ResponseWriter, r *http.Request) (*http.Requ
 		}
 	}
 	span.AddAttributes(requestAttrs(r)...)
+	if r.Body == nil {
+		// TODO: Handle cases where ContentLength is not set.
+	} else if r.ContentLength > 0 {
+		span.AddMessageReceiveEvent(0, /* TODO: messageID */
+			int64(r.ContentLength), -1)
+	}
 	return r.WithContext(ctx), span.End
 }
 
@@ -201,6 +207,9 @@ func (t *trackingResponseWriter) Header() http.Header {
 func (t *trackingResponseWriter) Write(data []byte) (int, error) {
 	n, err := t.writer.Write(data)
 	t.respSize += int64(n)
+	// Add message event for request bytes sent.
+	span := trace.FromContext(t.ctx)
+	span.AddMessageSendEvent(0 /* TODO: messageID */, int64(n), -1)
 	return n, err
 }
 
diff --git a/tag/map.go b/tag/map.go
index 5b72ba6..0272ef8 100644
--- a/tag/map.go
+++ b/tag/map.go
@@ -28,10 +28,15 @@ type Tag struct {
 	Value string
 }
 
+type tagContent struct {
+	value string
+	m     metadatas
+}
+
 // Map is a map of tags. Use New to create a context containing
 // a new Map.
 type Map struct {
-	m map[Key]string
+	m map[Key]tagContent
 }
 
 // Value returns the value for the key if a value for the key exists.
@@ -40,7 +45,7 @@ func (m *Map) Value(k Key) (string, bool) {
 		return "", false
 	}
 	v, ok := m.m[k]
-	return v, ok
+	return v.value, ok
 }
 
 func (m *Map) String() string {
@@ -62,21 +67,21 @@ func (m *Map) String() string {
 	return buffer.String()
 }
 
-func (m *Map) insert(k Key, v string) {
+func (m *Map) insert(k Key, v string, md metadatas) {
 	if _, ok := m.m[k]; ok {
 		return
 	}
-	m.m[k] = v
+	m.m[k] = tagContent{value: v, m: md}
 }
 
-func (m *Map) update(k Key, v string) {
+func (m *Map) update(k Key, v string, md metadatas) {
 	if _, ok := m.m[k]; ok {
-		m.m[k] = v
+		m.m[k] = tagContent{value: v, m: md}
 	}
 }
 
-func (m *Map) upsert(k Key, v string) {
-	m.m[k] = v
+func (m *Map) upsert(k Key, v string, md metadatas) {
+	m.m[k] = tagContent{value: v, m: md}
 }
 
 func (m *Map) delete(k Key) {
@@ -84,7 +89,7 @@ func (m *Map) delete(k Key) {
 }
 
 func newMap() *Map {
-	return &Map{m: make(map[Key]string)}
+	return &Map{m: make(map[Key]tagContent)}
 }
 
 // Mutator modifies a tag map.
@@ -95,13 +100,17 @@ type Mutator interface {
 // Insert returns a mutator that inserts a
 // value associated with k. If k already exists in the tag map,
 // mutator doesn't update the value.
-func Insert(k Key, v string) Mutator {
+// Metadata applies metadata to the tag. It is optional.
+// Metadatas are applied in the order in which it is provided.
+// If more than one metadata updates the same attribute then
+// the update from the last metadata prevails.
+func Insert(k Key, v string, mds ...Metadata) Mutator {
 	return &mutator{
 		fn: func(m *Map) (*Map, error) {
 			if !checkValue(v) {
 				return nil, errInvalidValue
 			}
-			m.insert(k, v)
+			m.insert(k, v, createMetadatas(mds...))
 			return m, nil
 		},
 	}
@@ -110,13 +119,17 @@ func Insert(k Key, v string) Mutator {
 // Update returns a mutator that updates the
 // value of the tag associated with k with v. If k doesn't
 // exists in the tag map, the mutator doesn't insert the value.
-func Update(k Key, v string) Mutator {
+// Metadata applies metadata to the tag. It is optional.
+// Metadatas are applied in the order in which it is provided.
+// If more than one metadata updates the same attribute then
+// the update from the last metadata prevails.
+func Update(k Key, v string, mds ...Metadata) Mutator {
 	return &mutator{
 		fn: func(m *Map) (*Map, error) {
 			if !checkValue(v) {
 				return nil, errInvalidValue
 			}
-			m.update(k, v)
+			m.update(k, v, createMetadatas(mds...))
 			return m, nil
 		},
 	}
@@ -126,18 +139,37 @@ func Update(k Key, v string) Mutator {
 // value of the tag associated with k with v. It inserts the
 // value if k doesn't exist already. It mutates the value
 // if k already exists.
-func Upsert(k Key, v string) Mutator {
+// Metadata applies metadata to the tag. It is optional.
+// Metadatas are applied in the order in which it is provided.
+// If more than one metadata updates the same attribute then
+// the update from the last metadata prevails.
+func Upsert(k Key, v string, mds ...Metadata) Mutator {
 	return &mutator{
 		fn: func(m *Map) (*Map, error) {
 			if !checkValue(v) {
 				return nil, errInvalidValue
 			}
-			m.upsert(k, v)
+			m.upsert(k, v, createMetadatas(mds...))
 			return m, nil
 		},
 	}
 }
 
+func createMetadatas(mds ...Metadata) metadatas {
+	var metas metadatas
+	if len(mds) > 0 {
+		for _, md := range mds {
+			if md != nil {
+				md(&metas)
+			}
+		}
+	} else {
+		WithTTL(TTLUnlimitedPropagation)(&metas)
+	}
+	return metas
+
+}
+
 // Delete returns a mutator that deletes
 // the value associated with k.
 func Delete(k Key) Mutator {
@@ -160,10 +192,10 @@ func New(ctx context.Context, mutator ...Mutator) (context.Context, error) {
 			if !checkKeyName(k.Name()) {
 				return ctx, fmt.Errorf("key:%q: %v", k, errInvalidKeyName)
 			}
-			if !checkValue(v) {
+			if !checkValue(v.value) {
 				return ctx, fmt.Errorf("key:%q value:%q: %v", k.Name(), v, errInvalidValue)
 			}
-			m.insert(k, v)
+			m.insert(k, v.value, v.m)
 		}
 	}
 	var err error
diff --git a/tag/map_codec.go b/tag/map_codec.go
index c14c7f6..f8b5827 100644
--- a/tag/map_codec.go
+++ b/tag/map_codec.go
@@ -170,9 +170,11 @@ func Encode(m *Map) []byte {
 	}
 	eg.writeByte(byte(tagsVersionID))
 	for k, v := range m.m {
-		eg.writeByte(byte(keyTypeString))
-		eg.writeStringWithVarintLen(k.name)
-		eg.writeBytesWithVarintLen([]byte(v))
+		if v.m.ttl.ttl == valueTTLUnlimitedPropagation {
+			eg.writeByte(byte(keyTypeString))
+			eg.writeStringWithVarintLen(k.name)
+			eg.writeBytesWithVarintLen([]byte(v.value))
+		}
 	}
 	return eg.bytes()
 }
@@ -190,7 +192,7 @@ func Decode(bytes []byte) (*Map, error) {
 
 // DecodeEach decodes the given serialized tag map, calling handler for each
 // tag key and value decoded.
-func DecodeEach(bytes []byte, fn func(key Key, val string)) error {
+func DecodeEach(bytes []byte, fn func(key Key, val string, md metadatas)) error {
 	eg := &encoderGRPC{
 		buf: bytes,
 	}
@@ -228,7 +230,10 @@ func DecodeEach(bytes []byte, fn func(key Key, val string)) error {
 		if !checkValue(val) {
 			return errInvalidValue
 		}
-		fn(key, val)
+		fn(key, val, createMetadatas(WithTTL(TTLUnlimitedPropagation)))
+		if err != nil {
+			return err
+		}
 	}
 	return nil
 }
diff --git a/tag/metadata.go b/tag/metadata.go
new file mode 100644
index 0000000..6571a58
--- /dev/null
+++ b/tag/metadata.go
@@ -0,0 +1,52 @@
+// 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.
+//
+
+package tag
+
+const (
+	// valueTTLNoPropagation prevents tag from propagating.
+	valueTTLNoPropagation = 0
+
+	// valueTTLUnlimitedPropagation allows tag to propagate without any limits on number of hops.
+	valueTTLUnlimitedPropagation = -1
+)
+
+// TTL is metadata that specifies number of hops a tag can propagate.
+// Details about TTL metadata is specified at https://github.com/census-instrumentation/opencensus-specs/blob/master/tags/TagMap.md#tagmetadata
+type TTL struct {
+	ttl int
+}
+
+var (
+	// TTLUnlimitedPropagation is TTL metadata that allows tag to propagate without any limits on number of hops.
+	TTLUnlimitedPropagation = TTL{ttl: valueTTLUnlimitedPropagation}
+
+	// TTLNoPropagation is TTL metadata that prevents tag from propagating.
+	TTLNoPropagation = TTL{ttl: valueTTLNoPropagation}
+)
+
+type metadatas struct {
+	ttl TTL
+}
+
+// Metadata applies metadatas specified by the function.
+type Metadata func(*metadatas)
+
+// WithTTL applies metadata with provided ttl.
+func WithTTL(ttl TTL) Metadata {
+	return func(m *metadatas) {
+		m.ttl = ttl
+	}
+}
diff --git a/tag/profile_19.go b/tag/profile_19.go
index f81cd0b..b34d95e 100644
--- a/tag/profile_19.go
+++ b/tag/profile_19.go
@@ -25,7 +25,7 @@ func do(ctx context.Context, f func(ctx context.Context)) {
 	m := FromContext(ctx)
 	keyvals := make([]string, 0, 2*len(m.m))
 	for k, v := range m.m {
-		keyvals = append(keyvals, k.Name(), v)
+		keyvals = append(keyvals, k.Name(), v.value)
 	}
 	pprof.Do(ctx, pprof.Labels(keyvals...), f)
 }


Test patch:
diff --git a/exporter/jaeger/example_test.go b/exporter/jaeger/example_test.go
deleted file mode 100644
index bb21207..0000000
--- a/exporter/jaeger/example_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2018, 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.
-
-package jaeger_test
-
-import (
-	"log"
-
-	"go.opencensus.io/exporter/jaeger"
-	"go.opencensus.io/trace"
-)
-
-func ExampleNewExporter_collector() {
-	// Register the Jaeger exporter to be able to retrieve
-	// the collected spans.
-	exporter, err := jaeger.NewExporter(jaeger.Options{
-		Endpoint: "http://localhost:14268",
-		Process: jaeger.Process{
-			ServiceName: "trace-demo",
-		},
-	})
-	if err != nil {
-		log.Fatal(err)
-	}
-	trace.RegisterExporter(exporter)
-}
-
-func ExampleNewExporter_agent() {
-	// Register the Jaeger exporter to be able to retrieve
-	// the collected spans.
-	exporter, err := jaeger.NewExporter(jaeger.Options{
-		AgentEndpoint: "localhost:6831",
-		Process: jaeger.Process{
-			ServiceName: "trace-demo",
-		},
-	})
-	if err != nil {
-		log.Fatal(err)
-	}
-	trace.RegisterExporter(exporter)
-}
-
-// ExampleNewExporter_processTags shows how to set ProcessTags
-// on a Jaeger exporter. These tags will be added to the exported
-// Jaeger process.
-func ExampleNewExporter_processTags() {
-	// Register the Jaeger exporter to be able to retrieve
-	// the collected spans.
-	exporter, err := jaeger.NewExporter(jaeger.Options{
-		AgentEndpoint: "localhost:6831",
-		Process: jaeger.Process{
-			ServiceName: "trace-demo",
-			Tags: []jaeger.Tag{
-				jaeger.StringTag("ip", "127.0.0.1"),
-				jaeger.BoolTag("demo", true),
-			},
-		},
-	})
-	if err != nil {
-		log.Fatal(err)
-	}
-	trace.RegisterExporter(exporter)
-}
diff --git a/exporter/jaeger/jaeger_test.go b/exporter/jaeger/jaeger_test.go
deleted file mode 100644
index f93b5dd..0000000
--- a/exporter/jaeger/jaeger_test.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2018, 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.
-
-package jaeger
-
-import (
-	"fmt"
-	"reflect"
-	"testing"
-	"time"
-
-	gen "go.opencensus.io/exporter/jaeger/internal/gen-go/jaeger"
-	"go.opencensus.io/trace"
-	"sort"
-)
-
-// TODO(jbd): Test export.
-
-func Test_bytesToInt64(t *testing.T) {
-	type args struct {
-	}
-	tests := []struct {
-		buf  []byte
-		want int64
-	}{
-		{
-			buf:  []byte{255, 0, 0, 0, 0, 0, 0, 0},
-			want: -72057594037927936,
-		},
-		{
-			buf:  []byte{0, 0, 0, 0, 0, 0, 0, 1},
-			want: 1,
-		},
-		{
-			buf:  []byte{0, 0, 0, 0, 0, 0, 0, 0},
-			want: 0,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(fmt.Sprintf("%d", tt.want), func(t *testing.T) {
-			if got := bytesToInt64(tt.buf); got != tt.want {
-				t.Errorf("bytesToInt64() = \n%v, \n want \n%v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_spanDataToThrift(t *testing.T) {
-	now := time.Now()
-
-	answerValue := int64(42)
-	keyValue := "value"
-	resultValue := true
-	statusCodeValue := int64(2)
-	doubleValue := float64(123.456)
-	boolTrue := true
-	statusMessage := "error"
-
-	tests := []struct {
-		name string
-		data *trace.SpanData
-		want *gen.Span
-	}{
-		{
-			name: "no parent",
-			data: &trace.SpanData{
-				SpanContext: trace.SpanContext{
-					TraceID: trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
-					SpanID:  trace.SpanID{1, 2, 3, 4, 5, 6, 7, 8},
-				},
-				Name:      "/foo",
-				StartTime: now,
-				EndTime:   now,
-				Attributes: map[string]interface{}{
-					"double": doubleValue,
-					"key":    keyValue,
-				},
-				Annotations: []trace.Annotation{
-					{
-						Time:    now,
-						Message: statusMessage,
-						Attributes: map[string]interface{}{
-							"answer": answerValue,
-						},
-					},
-					{
-						Time:    now,
-						Message: statusMessage,
-						Attributes: map[string]interface{}{
-							"result": resultValue,
-						},
-					},
-				},
-				Status: trace.Status{Code: trace.StatusCodeUnknown, Message: "error"},
-			},
-			want: &gen.Span{
-				TraceIdLow:    651345242494996240,
-				TraceIdHigh:   72623859790382856,
-				SpanId:        72623859790382856,
-				OperationName: "/foo",
-				StartTime:     now.UnixNano() / 1000,
-				Duration:      0,
-				Tags: []*gen.Tag{
-					{Key: "double", VType: gen.TagType_DOUBLE, VDouble: &doubleValue},
-					{Key: "key", VType: gen.TagType_STRING, VStr: &keyValue},
-					{Key: "error", VType: gen.TagType_BOOL, VBool: &boolTrue},
-					{Key: "status.code", VType: gen.TagType_LONG, VLong: &statusCodeValue},
-					{Key: "status.message", VType: gen.TagType_STRING, VStr: &statusMessage},
-				},
-				Logs: []*gen.Log{
-					{Timestamp: now.UnixNano() / 1000, Fields: []*gen.Tag{
-						{Key: "answer", VType: gen.TagType_LONG, VLong: &answerValue},
-						{Key: "message", VType: gen.TagType_STRING, VStr: &statusMessage},
-					}},
-					{Timestamp: now.UnixNano() / 1000, Fields: []*gen.Tag{
-						{Key: "result", VType: gen.TagType_BOOL, VBool: &resultValue},
-						{Key: "message", VType: gen.TagType_STRING, VStr: &statusMessage},
-					}},
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			got := spanDataToThrift(tt.data)
-			sort.Slice(got.Tags, func(i, j int) bool {
-				return got.Tags[i].Key < got.Tags[j].Key
-			})
-			sort.Slice(tt.want.Tags, func(i, j int) bool {
-				return tt.want.Tags[i].Key < tt.want.Tags[j].Key
-			})
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("spanDataToThrift()\nGot:\n%v\nWant;\n%v", got, tt.want)
-			}
-		})
-	}
-}
diff --git a/exporter/prometheus/example_test.go b/exporter/prometheus/example_test.go
deleted file mode 100644
index 182ad20..0000000
--- a/exporter/prometheus/example_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2018, 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.
-
-package prometheus_test
-
-import (
-	"log"
-	"net/http"
-
-	"go.opencensus.io/exporter/prometheus"
-)
-
-func Example() {
-	exporter, err := prometheus.NewExporter(prometheus.Options{})
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	// Serve the scrape endpoint on port 9999.
-	http.Handle("/metrics", exporter)
-	log.Fatal(http.ListenAndServe(":9999", nil))
-}
diff --git a/exporter/prometheus/prometheus_test.go b/exporter/prometheus/prometheus_test.go
deleted file mode 100644
index 83fc90a..0000000
--- a/exporter/prometheus/prometheus_test.go
+++ /dev/null
@@ -1,450 +0,0 @@
-// Copyright 2017, 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.
-
-package prometheus
-
-import (
-	"context"
-	"io/ioutil"
-	"net/http"
-	"net/http/httptest"
-	"strings"
-	"testing"
-	"time"
-
-	"go.opencensus.io/stats"
-	"go.opencensus.io/stats/view"
-	"go.opencensus.io/tag"
-
-	"github.com/prometheus/client_golang/prometheus"
-)
-
-type mSlice []*stats.Int64Measure
-
-func (measures *mSlice) createAndAppend(name, desc, unit string) {
-	m := stats.Int64(name, desc, unit)
-	*measures = append(*measures, m)
-}
-
-type vCreator []*view.View
-
-func (vc *vCreator) createAndAppend(name, description string, keys []tag.Key, measure stats.Measure, agg *view.Aggregation) {
-	v := &view.View{
-		Name:        name,
-		Description: description,
-		TagKeys:     keys,
-		Measure:     measure,
-		Aggregation: agg,
-	}
-	*vc = append(*vc, v)
-}
-
-func TestMetricsEndpointOutput(t *testing.T) {
-	exporter, err := NewExporter(Options{})
-	if err != nil {
-		t.Fatalf("failed to create prometheus exporter: %v", err)
-	}
-
-	names := []string{"foo", "bar", "baz"}
-
-	var measures mSlice
-	for _, name := range names {
-		measures.createAndAppend("tests/"+name, name, "")
-	}
-
-	var vc vCreator
-	for _, m := range measures {
-		vc.createAndAppend(m.Name(), m.Description(), nil, m, view.Count())
-	}
-
-	if err := view.Register(vc...); err != nil {
-		t.Fatalf("failed to create views: %v", err)
-	}
-	defer view.Unregister(vc...)
-
-	view.SetReportingPeriod(time.Millisecond)
-
-	for _, m := range measures {
-		stats.Record(context.Background(), m.M(1))
-	}
-
-	srv := httptest.NewServer(exporter)
-	defer srv.Close()
-
-	var i int
-	var output string
-	for {
-		time.Sleep(10 * time.Millisecond)
-		if i == 1000 {
-			t.Fatal("no output at /metrics (10s wait)")
-		}
-		i++
-
-		resp, err := http.Get(srv.URL)
-		if err != nil {
-			t.Fatalf("failed to get /metrics: %v", err)
-		}
-
-		body, err := ioutil.ReadAll(resp.Body)
-		if err != nil {
-			t.Fatalf("failed to read body: %v", err)
-		}
-		resp.Body.Close()
-
-		output = string(body)
-		if output != "" {
-			break
-		}
-	}
-
-	if strings.Contains(output, "collected before with the same name and label values") {
-		t.Fatal("metric name and labels being duplicated but must be unique")
-	}
-
-	if strings.Contains(output, "error(s) occurred") {
-		t.Fatal("error reported by prometheus registry")
-	}
-
-	for _, name := range names {
-		if !strings.Contains(output, "tests_"+name+" 1") {
-			t.Fatalf("measurement missing in output: %v", name)
-		}
-	}
-}
-
-func TestCumulativenessFromHistograms(t *testing.T) {
-	exporter, err := NewExporter(Options{})
-	if err != nil {
-		t.Fatalf("failed to create prometheus exporter: %v", err)
-	}
-
-	m := stats.Float64("tests/bills", "payments by denomination", stats.UnitDimensionless)
-	v := &view.View{
-		Name:        "cash/register",
-		Description: "this is a test",
-		Measure:     m,
-
-		// Intentionally used repeated elements in the ascending distribution.
-		// to ensure duplicate distribution items are handles.
-		Aggregation: view.Distribution(1, 5, 5, 5, 5, 10, 20, 50, 100, 250),
-	}
-
-	if err := view.Register(v); err != nil {
-		t.Fatalf("Register error: %v", err)
-	}
-	defer view.Unregister(v)
-
-	// Give the reporter ample time to process registration
-	//<-time.After(10 * reportPeriod)
-
-	values := []float64{0.25, 245.67, 12, 1.45, 199.9, 7.69, 187.12}
-	// We want the results that look like this:
-	// 1:   [0.25]      		| 1 + prev(i) = 1 + 0 = 1
-	// 5:   [1.45]			| 1 + prev(i) = 1 + 1 = 2
-	// 10:	[7.69]			| 1 + prev(i) = 1 + 2 = 3
-	// 20:  [12]			| 1 + prev(i) = 1 + 3 = 4
-	// 50:  []			| 0 + prev(i) = 0 + 4 = 4
-	// 100: []			| 0 + prev(i) = 0 + 4 = 4
-	// 250: [187.12, 199.9, 245.67]	| 3 + prev(i) = 3 + 4 = 7
-	wantLines := []string{
-		`cash_register_bucket{le="1"} 1`,
-		`cash_register_bucket{le="5"} 2`,
-		`cash_register_bucket{le="10"} 3`,
-		`cash_register_bucket{le="20"} 4`,
-		`cash_register_bucket{le="50"} 4`,
-		`cash_register_bucket{le="100"} 4`,
-		`cash_register_bucket{le="250"} 7`,
-		`cash_register_bucket{le="+Inf"} 7`,
-		`cash_register_sum 654.0799999999999`, // Summation of the input values
-		`cash_register_count 7`,
-	}
-
-	ctx := context.Background()
-	ms := make([]stats.Measurement, 0, len(values))
-	for _, value := range values {
-		mx := m.M(value)
-		ms = append(ms, mx)
-	}
-	stats.Record(ctx, ms...)
-
-	// Give the recorder ample time to process recording
-	//<-time.After(10 * reportPeriod)
-
-	cst := httptest.NewServer(exporter)
-	defer cst.Close()
-	res, err := http.Get(cst.URL)
-	if err != nil {
-		t.Fatalf("http.Get error: %v", err)
-	}
-	blob, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Fatalf("Read body error: %v", err)
-	}
-	str := strings.Trim(string(blob), "\n")
-	lines := strings.Split(str, "\n")
-	nonComments := make([]string, 0, len(lines))
-	for _, line := range lines {
-		if !strings.Contains(line, "#") {
-			nonComments = append(nonComments, line)
-		}
-	}
-
-	got := strings.Join(nonComments, "\n")
-	want := strings.Join(wantLines, "\n")
-	if got != want {
-		t.Fatalf("\ngot:\n%s\n\nwant:\n%s\n", got, want)
-	}
-}
-
-func TestHistogramUnorderedBucketBounds(t *testing.T) {
-	exporter, err := NewExporter(Options{})
-	if err != nil {
-		t.Fatalf("failed to create prometheus exporter: %v", err)
-	}
-
-	m := stats.Float64("tests/bills", "payments by denomination", stats.UnitDimensionless)
-	v := &view.View{
-		Name:        "cash/register",
-		Description: "this is a test",
-		Measure:     m,
-
-		// Intentionally used unordered and duplicated elements in the distribution
-		// to ensure unordered bucket bounds are handled.
-		Aggregation: view.Distribution(10, 5, 1, 1, 50, 5, 20, 100, 250),
-	}
-
-	if err := view.Register(v); err != nil {
-		t.Fatalf("Register error: %v", err)
-	}
-	defer view.Unregister(v)
-
-	// Give the reporter ample time to process registration
-	//<-time.After(10 * reportPeriod)
-
-	values := []float64{0.25, 245.67, 12, 1.45, 199.9, 7.69, 187.12}
-	// We want the results that look like this:
-	// 1:   [0.25]      		| 1 + prev(i) = 1 + 0 = 1
-	// 5:   [1.45]			| 1 + prev(i) = 1 + 1 = 2
-	// 10:	[7.69]			| 1 + prev(i) = 1 + 2 = 3
-	// 20:  [12]			| 1 + prev(i) = 1 + 3 = 4
-	// 50:  []			| 0 + prev(i) = 0 + 4 = 4
-	// 100: []			| 0 + prev(i) = 0 + 4 = 4
-	// 250: [187.12, 199.9, 245.67]	| 3 + prev(i) = 3 + 4 = 7
-	wantLines := []string{
-		`cash_register_bucket{le="1"} 1`,
-		`cash_register_bucket{le="5"} 2`,
-		`cash_register_bucket{le="10"} 3`,
-		`cash_register_bucket{le="20"} 4`,
-		`cash_register_bucket{le="50"} 4`,
-		`cash_register_bucket{le="100"} 4`,
-		`cash_register_bucket{le="250"} 7`,
-		`cash_register_bucket{le="+Inf"} 7`,
-		`cash_register_sum 654.0799999999999`, // Summation of the input values
-		`cash_register_count 7`,
-	}
-
-	ctx := context.Background()
-	ms := make([]stats.Measurement, 0, len(values))
-	for _, value := range values {
-		mx := m.M(value)
-		ms = append(ms, mx)
-	}
-	stats.Record(ctx, ms...)
-
-	// Give the recorder ample time to process recording
-	//<-time.After(10 * reportPeriod)
-
-	cst := httptest.NewServer(exporter)
-	defer cst.Close()
-	res, err := http.Get(cst.URL)
-	if err != nil {
-		t.Fatalf("http.Get error: %v", err)
-	}
-	blob, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Fatalf("Read body error: %v", err)
-	}
-	str := strings.Trim(string(blob), "\n")
-	lines := strings.Split(str, "\n")
-	nonComments := make([]string, 0, len(lines))
-	for _, line := range lines {
-		if !strings.Contains(line, "#") {
-			nonComments = append(nonComments, line)
-		}
-	}
-
-	got := strings.Join(nonComments, "\n")
-	want := strings.Join(wantLines, "\n")
-	if got != want {
-		t.Fatalf("\ngot:\n%s\n\nwant:\n%s\n", got, want)
-	}
-}
-
-func TestConstLabelsIncluded(t *testing.T) {
-	constLabels := prometheus.Labels{
-		"service": "spanner",
-	}
-	measureLabel, _ := tag.NewKey("method")
-
-	exporter, err := NewExporter(Options{
-		ConstLabels: constLabels,
-	})
-	if err != nil {
-		t.Fatalf("failed to create prometheus exporter: %v", err)
-	}
-
-	names := []string{"foo", "bar", "baz"}
-
-	var measures mSlice
-	for _, name := range names {
-		measures.createAndAppend("tests/"+name, name, "")
-	}
-
-	var vc vCreator
-	for _, m := range measures {
-		vc.createAndAppend(m.Name(), m.Description(), []tag.Key{measureLabel}, m, view.Count())
-	}
-
-	if err := view.Register(vc...); err != nil {
-		t.Fatalf("failed to create views: %v", err)
-	}
-	defer view.Unregister(vc...)
-
-	view.SetReportingPeriod(time.Millisecond)
-
-	ctx, _ := tag.New(context.Background(), tag.Upsert(measureLabel, "issue961"))
-	for _, m := range measures {
-		stats.Record(ctx, m.M(1))
-	}
-
-	srv := httptest.NewServer(exporter)
-	defer srv.Close()
-
-	var i int
-	var output string
-	for {
-		time.Sleep(10 * time.Millisecond)
-		if i == 1000 {
-			t.Fatal("no output at /metrics (10s wait)")
-		}
-		i++
-
-		resp, err := http.Get(srv.URL)
-		if err != nil {
-			t.Fatalf("failed to get /metrics: %v", err)
-		}
-
-		body, err := ioutil.ReadAll(resp.Body)
-		if err != nil {
-			t.Fatalf("failed to read body: %v", err)
-		}
-		resp.Body.Close()
-
-		output = string(body)
-		if output != "" {
-			break
-		}
-	}
-
-	if strings.Contains(output, "collected before with the same name and label values") {
-		t.Fatal("metric name and labels being duplicated but must be unique")
-	}
-
-	if strings.Contains(output, "error(s) occurred") {
-		t.Fatal("error reported by prometheus registry")
-	}
-
-	want := `# HELP tests_bar bar
-# TYPE tests_bar counter
-tests_bar{method="issue961",service="spanner"} 1
-# HELP tests_baz baz
-# TYPE tests_baz counter
-tests_baz{method="issue961",service="spanner"} 1
-# HELP tests_foo foo
-# TYPE tests_foo counter
-tests_foo{method="issue961",service="spanner"} 1
-`
-	if output != want {
-		t.Fatal("output differed from expected")
-	}
-}
-
-func TestViewMeasureWithoutTag(t *testing.T) {
-	exporter, err := NewExporter(Options{})
-	if err != nil {
-		t.Fatalf("failed to create prometheus exporter: %v", err)
-	}
-	m := stats.Int64("tests/foo", "foo", stats.UnitDimensionless)
-	k1, _ := tag.NewKey("key/1")
-	k2, _ := tag.NewKey("key/2")
-	k3, _ := tag.NewKey("key/3")
-	k4, _ := tag.NewKey("key/4")
-	k5, _ := tag.NewKey("key/5")
-	randomKey, _ := tag.NewKey("issue659")
-	v := &view.View{
-		Name:        m.Name(),
-		Description: m.Description(),
-		TagKeys:     []tag.Key{k2, k5, k3, k1, k4}, // Ensure view has a tag
-		Measure:     m,
-		Aggregation: view.Count(),
-	}
-	if err := view.Register(v); err != nil {
-		t.Fatalf("failed to create views: %v", err)
-	}
-	defer view.Unregister(v)
-	view.SetReportingPeriod(time.Millisecond)
-	// Make a measure without some tags in the view.
-	ctx1, _ := tag.New(context.Background(), tag.Upsert(k4, "issue659"), tag.Upsert(randomKey, "value"), tag.Upsert(k2, "issue659"))
-	stats.Record(ctx1, m.M(1))
-	ctx2, _ := tag.New(context.Background(), tag.Upsert(k5, "issue659"), tag.Upsert(k3, "issue659"), tag.Upsert(k1, "issue659"))
-	stats.Record(ctx2, m.M(2))
-	srv := httptest.NewServer(exporter)
-	defer srv.Close()
-	var i int
-	var output string
-	for {
-		time.Sleep(10 * time.Millisecond)
-		if i == 1000 {
-			t.Fatal("no output at /metrics (10s wait)")
-		}
-		i++
-		resp, err := http.Get(srv.URL)
-		if err != nil {
-			t.Fatalf("failed to get /metrics: %v", err)
-		}
-		body, err := ioutil.ReadAll(resp.Body)
-		if err != nil {
-			t.Fatalf("failed to read body: %v", err)
-		}
-		resp.Body.Close()
-		output = string(body)
-		if output != "" {
-			break
-		}
-	}
-	if strings.Contains(output, "collected before with the same name and label values") {
-		t.Fatal("metric name and labels being duplicated but must be unique")
-	}
-	if strings.Contains(output, "error(s) occurred") {
-		t.Fatal("error reported by prometheus registry")
-	}
-	want := `# HELP tests_foo foo
-# TYPE tests_foo counter
-tests_foo{key_1="",key_2="issue659",key_3="",key_4="issue659",key_5=""} 1
-tests_foo{key_1="issue659",key_2="",key_3="issue659",key_4="",key_5="issue659"} 1
-`
-	if output != want {
-		t.Fatalf("output differed from expected output: %s want: %s", output, want)
-	}
-}
diff --git a/exporter/zipkin/example_test.go b/exporter/zipkin/example_test.go
deleted file mode 100644
index 7ef1470..0000000
--- a/exporter/zipkin/example_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2018, 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.
-
-package zipkin_test
-
-import (
-	"log"
-
-	openzipkin "github.com/openzipkin/zipkin-go"
-	"github.com/openzipkin/zipkin-go/reporter/http"
-	"go.opencensus.io/exporter/zipkin"
-	"go.opencensus.io/trace"
-)
-
-func Example() {
-	// import (
-	//     openzipkin "github.com/openzipkin/zipkin-go"
-	//     "github.com/openzipkin/zipkin-go/reporter/http"
-	//     "go.opencensus.io/exporter/trace/zipkin"
-	// )
-
-	localEndpoint, err := openzipkin.NewEndpoint("server", "192.168.1.5:5454")
-	if err != nil {
-		log.Print(err)
-	}
-	reporter := http.NewReporter("http://localhost:9411/api/v2/spans")
-	exporter := zipkin.NewExporter(reporter, localEndpoint)
-	trace.RegisterExporter(exporter)
-}
diff --git a/exporter/zipkin/zipkin_test.go b/exporter/zipkin/zipkin_test.go
deleted file mode 100644
index c2b5420..0000000
--- a/exporter/zipkin/zipkin_test.go
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2017, 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.
-
-package zipkin
-
-import (
-	"encoding/json"
-	"io/ioutil"
-	"net/http"
-	"reflect"
-	"strings"
-	"testing"
-	"time"
-
-	"github.com/openzipkin/zipkin-go/model"
-	httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
-	"go.opencensus.io/trace"
-)
-
-type roundTripper func(*http.Request) (*http.Response, error)
-
-func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
-	return r(req)
-}
-
-func TestExport(t *testing.T) {
-	// Since Zipkin reports in microsecond resolution let's round our Timestamp,
-	// so when deserializing Zipkin data in this test we can properly compare.
-	now := time.Now().Round(time.Microsecond)
-	tests := []struct {
-		span *trace.SpanData
-		want model.SpanModel
-	}{
-		{
-			span: &trace.SpanData{
-				SpanContext: trace.SpanContext{
-					TraceID:      trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
-					SpanID:       trace.SpanID{17, 18, 19, 20, 21, 22, 23, 24},
-					TraceOptions: 1,
-				},
-				Name:      "name",
-				SpanKind:  trace.SpanKindClient,
-				StartTime: now,
-				EndTime:   now.Add(24 * time.Hour),
-				Attributes: map[string]interface{}{
-					"stringkey": "value",
-					"intkey":    int64(42),
-					"boolkey1":  true,
-					"boolkey2":  false,
-					"doublekey": float64(123.456),
-				},
-				MessageEvents: []trace.MessageEvent{
-					{
-						Time:                 now,
-						EventType:            trace.MessageEventTypeSent,
-						MessageID:            12,
-						UncompressedByteSize: 99,
-						CompressedByteSize:   98,
-					},
-				},
-				Annotations: []trace.Annotation{
-					{
-						Time:    now,
-						Message: "Annotation",
-						Attributes: map[string]interface{}{
-							"stringkey": "value",
-							"intkey":    int64(42),
-							"boolkey1":  true,
-							"boolkey2":  false,
-							"doublekey": float64(123.456),
-						},
-					},
-				},
-				Status: trace.Status{
-					Code:    3,
-					Message: "error",
-				},
-			},
-			want: model.SpanModel{
-				SpanContext: model.SpanContext{
-					TraceID: model.TraceID{
-						High: 0x0102030405060708,
-						Low:  0x090a0b0c0d0e0f10,
-					},
-					ID:      0x1112131415161718,
-					Sampled: &sampledTrue,
-				},
-				Name:      "name",
-				Kind:      model.Client,
-				Timestamp: now,
-				Duration:  24 * time.Hour,
-				Shared:    false,
-				Annotations: []model.Annotation{
-					{
-						Timestamp: now,
-						Value:     "Annotation",
-					},
-					{
-						Timestamp: now,
-						Value:     "SENT",
-					},
-				},
-				Tags: map[string]string{
-					"stringkey":                     "value",
-					"intkey":                        "42",
-					"boolkey1":                      "true",
-					"boolkey2":                      "false",
-					"doublekey":                     "123.456",
-					"error":                         "INVALID_ARGUMENT",
-					"opencensus.status_description": "error",
-				},
-			},
-		},
-		{
-			span: &trace.SpanData{
-				SpanContext: trace.SpanContext{
-					TraceID:      trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
-					SpanID:       trace.SpanID{17, 18, 19, 20, 21, 22, 23, 24},
-					TraceOptions: 1,
-				},
-				Name:      "name",
-				StartTime: now,
-				EndTime:   now.Add(24 * time.Hour),
-			},
-			want: model.SpanModel{
-				SpanContext: model.SpanContext{
-					TraceID: model.TraceID{
-						High: 0x0102030405060708,
-						Low:  0x090a0b0c0d0e0f10,
-					},
-					ID:      0x1112131415161718,
-					Sampled: &sampledTrue,
-				},
-				Name:      "name",
-				Timestamp: now,
-				Duration:  24 * time.Hour,
-				Shared:    false,
-			},
-		},
-		{
-			span: &trace.SpanData{
-				SpanContext: trace.SpanContext{
-					TraceID:      trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
-					SpanID:       trace.SpanID{17, 18, 19, 20, 21, 22, 23, 24},
-					TraceOptions: 1,
-				},
-				Name:      "name",
-				StartTime: now,
-				EndTime:   now.Add(24 * time.Hour),
-				Status: trace.Status{
-					Code:    0,
-					Message: "there is no cause for alarm",
-				},
-			},
-			want: model.SpanModel{
-				SpanContext: model.SpanContext{
-					TraceID: model.TraceID{
-						High: 0x0102030405060708,
-						Low:  0x090a0b0c0d0e0f10,
-					},
-					ID:      0x1112131415161718,
-					Sampled: &sampledTrue,
-				},
-				Name:      "name",
-				Timestamp: now,
-				Duration:  24 * time.Hour,
-				Shared:    false,
-				Tags: map[string]string{
-					"opencensus.status_description": "there is no cause for alarm",
-				},
-			},
-		},
-		{
-			span: &trace.SpanData{
-				SpanContext: trace.SpanContext{
-					TraceID:      trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
-					SpanID:       trace.SpanID{17, 18, 19, 20, 21, 22, 23, 24},
-					TraceOptions: 1,
-				},
-				Name:      "name",
-				StartTime: now,
-				EndTime:   now.Add(24 * time.Hour),
-				Status: trace.Status{
-					Code: 1234,
-				},
-			},
-			want: model.SpanModel{
-				SpanContext: model.SpanContext{
-					TraceID: model.TraceID{
-						High: 0x0102030405060708,
-						Low:  0x090a0b0c0d0e0f10,
-					},
-					ID:      0x1112131415161718,
-					Sampled: &sampledTrue,
-				},
-				Name:      "name",
-				Timestamp: now,
-				Duration:  24 * time.Hour,
-				Shared:    false,
-				Tags: map[string]string{
-					"error": "error code 1234",
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		got := zipkinSpan(tt.span, nil)
-		if len(got.Annotations) != len(tt.want.Annotations) {
-			t.Fatalf("zipkinSpan: got %d annotations in span, want %d", len(got.Annotations), len(tt.want.Annotations))
-		}
-		if !reflect.DeepEqual(got, tt.want) {
-			t.Errorf("zipkinSpan:\n\tgot  %#v\n\twant %#v", got, tt.want)
-		}
-	}
-	for _, tt := range tests {
-		ch := make(chan []byte)
-		client := http.Client{
-			Transport: roundTripper(func(req *http.Request) (*http.Response, error) {
-				body, _ := ioutil.ReadAll(req.Body)
-				ch <- body
-				return &http.Response{StatusCode: 200, Body: ioutil.NopCloser(strings.NewReader(""))}, nil
-			}),
-		}
-		reporter := httpreporter.NewReporter("foo", httpreporter.Client(&client), httpreporter.BatchInterval(time.Millisecond))
-		exporter := NewExporter(reporter, nil)
-		exporter.ExportSpan(tt.span)
-		var data []byte
-		select {
-		case data = <-ch:
-		case <-time.After(2 * time.Second):
-			t.Fatalf("span was not exported")
-		}
-		var spans []model.SpanModel
-		json.Unmarshal(data, &spans)
-		if len(spans) != 1 {
-			t.Fatalf("Export: got %d spans, want 1", len(spans))
-		}
-		got := spans[0]
-		got.SpanContext.Sampled = &sampledTrue // Sampled is not set when the span is reported.
-		if len(got.Annotations) != len(tt.want.Annotations) {
-			t.Fatalf("Export: got %d annotations in span, want %d", len(got.Annotations), len(tt.want.Annotations))
-		}
-		if !reflect.DeepEqual(got, tt.want) {
-			t.Errorf("Export:\n\tgot  %#v\n\twant %#v", got, tt.want)
-		}
-	}
-}
diff --git a/metric/cumulative_test.go b/metric/cumulative_test.go
index 6b2110d..98bda94 100644
--- a/metric/cumulative_test.go
+++ b/metric/cumulative_test.go
@@ -19,6 +19,7 @@ import (
 	"time"
 
 	"github.com/google/go-cmp/cmp"
+
 	"go.opencensus.io/metric/metricdata"
 )
 
@@ -83,6 +84,61 @@ func TestCumulative(t *testing.T) {
 	}
 }
 
+func TestCumulativeConstLabel(t *testing.T) {
+	r := NewRegistry()
+
+	f, _ := r.AddFloat64Cumulative("TestCumulativeWithConstLabel",
+		WithLabelKeys("k1"),
+		WithConstLabel(map[metricdata.LabelKey]metricdata.LabelValue{
+			{Key: "const"}:  metricdata.NewLabelValue("same"),
+			{Key: "const2"}: metricdata.NewLabelValue("same2"),
+		}))
+
+	e, _ := f.GetEntry(metricdata.LabelValue{})
+	e.Inc(5)
+	e, _ = f.GetEntry(metricdata.NewLabelValue("k1v1"))
+	e.Inc(1)
+	m := r.Read()
+	want := []*metricdata.Metric{
+		{
+			Descriptor: metricdata.Descriptor{
+				Name: "TestCumulativeWithConstLabel",
+				LabelKeys: []metricdata.LabelKey{
+					{Key: "const"},
+					{Key: "const2"},
+					{Key: "k1"}},
+				Type: metricdata.TypeCumulativeFloat64,
+			},
+			TimeSeries: []*metricdata.TimeSeries{
+				{
+					LabelValues: []metricdata.LabelValue{
+						metricdata.NewLabelValue("same"),
+						metricdata.NewLabelValue("same2"),
+						{}},
+					Points: []metricdata.Point{
+						metricdata.NewFloat64Point(time.Time{}, 5),
+					},
+				},
+				{
+					LabelValues: []metricdata.LabelValue{
+						metricdata.NewLabelValue("same"),
+						metricdata.NewLabelValue("same2"),
+						metricdata.NewLabelValue("k1v1"),
+					},
+					Points: []metricdata.Point{
+						metricdata.NewFloat64Point(time.Time{}, 1),
+					},
+				},
+			},
+		},
+	}
+	canonicalize(m)
+	canonicalize(want)
+	if diff := cmp.Diff(m, want, cmp.Comparer(ignoreTimes)); diff != "" {
+		t.Errorf("-got +want: %s", diff)
+	}
+}
+
 func TestCumulativeMetricDescriptor(t *testing.T) {
 	r := NewRegistry()
 
diff --git a/metric/gauge_test.go b/metric/gauge_test.go
index a352d2d..9c4f269 100644
--- a/metric/gauge_test.go
+++ b/metric/gauge_test.go
@@ -16,12 +16,13 @@ package metric
 
 import (
 	"fmt"
-	"go.opencensus.io/metric/metricdata"
 	"sort"
 	"testing"
 	"time"
 
 	"github.com/google/go-cmp/cmp"
+
+	"go.opencensus.io/metric/metricdata"
 )
 
 func TestGauge(t *testing.T) {
@@ -85,6 +86,62 @@ func TestGauge(t *testing.T) {
 	}
 }
 
+func TestGaugeConstLabel(t *testing.T) {
+	r := NewRegistry()
+
+	f, _ := r.AddFloat64Gauge("TestGaugeWithConstLabel",
+		WithLabelKeys("k1"),
+		WithConstLabel(map[metricdata.LabelKey]metricdata.LabelValue{
+			{Key: "const"}:  metricdata.NewLabelValue("same"),
+			{Key: "const2"}: metricdata.NewLabelValue("same2"),
+		}))
+
+	e, _ := f.GetEntry(metricdata.LabelValue{})
+	e.Set(5)
+	e, _ = f.GetEntry(metricdata.NewLabelValue("k1v1"))
+	e.Add(1)
+	m := r.Read()
+	want := []*metricdata.Metric{
+		{
+			Descriptor: metricdata.Descriptor{
+				Name: "TestGaugeWithConstLabel",
+				LabelKeys: []metricdata.LabelKey{
+					{Key: "const"},
+					{Key: "const2"},
+					{Key: "k1"}},
+				Type: metricdata.TypeGaugeFloat64,
+			},
+			TimeSeries: []*metricdata.TimeSeries{
+				{
+					LabelValues: []metricdata.LabelValue{
+						metricdata.NewLabelValue("same"),
+						metricdata.NewLabelValue("same2"),
+						{},
+					},
+					Points: []metricdata.Point{
+						metricdata.NewFloat64Point(time.Time{}, 5),
+					},
+				},
+				{
+					LabelValues: []metricdata.LabelValue{
+						metricdata.NewLabelValue("same"),
+						metricdata.NewLabelValue("same2"),
+						metricdata.NewLabelValue("k1v1"),
+					},
+					Points: []metricdata.Point{
+						metricdata.NewFloat64Point(time.Time{}, 1),
+					},
+				},
+			},
+		},
+	}
+	canonicalize(m)
+	canonicalize(want)
+	if diff := cmp.Diff(m, want, cmp.Comparer(ignoreTimes)); diff != "" {
+		t.Errorf("-got +want: %s", diff)
+	}
+}
+
 func TestGaugeMetricDescriptor(t *testing.T) {
 	r := NewRegistry()
 
@@ -330,20 +387,18 @@ func canonicalize(ms []*metricdata.Metric) {
 	for _, m := range ms {
 		sort.Slice(m.TimeSeries, func(i, j int) bool {
 			// sort time series by their label values
-			iLabels := m.TimeSeries[i].LabelValues
-			jLabels := m.TimeSeries[j].LabelValues
-			for k := 0; k < len(iLabels); k++ {
-				if !iLabels[k].Present {
-					if jLabels[k].Present {
-						return true
-					}
-				} else if !jLabels[k].Present {
-					return false
-				} else {
-					return iLabels[k].Value < jLabels[k].Value
-				}
+			iStr := ""
+
+			for _, label := range m.TimeSeries[i].LabelValues {
+				iStr += fmt.Sprintf("%+v", label)
 			}
-			panic("should have returned")
+
+			jStr := ""
+			for _, label := range m.TimeSeries[j].LabelValues {
+				jStr += fmt.Sprintf("%+v", label)
+			}
+
+			return iStr < jStr
 		})
 	}
 }
diff --git a/plugin/ocgrpc/client_stats_handler_test.go b/plugin/ocgrpc/client_stats_handler_test.go
index 53f9248..e9197fc 100644
--- a/plugin/ocgrpc/client_stats_handler_test.go
+++ b/plugin/ocgrpc/client_stats_handler_test.go
@@ -16,14 +16,19 @@
 package ocgrpc
 
 import (
+	"reflect"
 	"testing"
 
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+
 	"go.opencensus.io/trace"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 
 	"golang.org/x/net/context"
 
+	"go.opencensus.io/metric/metricdata"
 	"go.opencensus.io/stats/view"
 	"go.opencensus.io/tag"
 
@@ -334,6 +339,72 @@ func TestClientDefaultCollections(t *testing.T) {
 	}
 }
 
+func TestClientRecordExemplar(t *testing.T) {
+	key, _ := tag.NewKey("test_key")
+	tagInfo := &stats.RPCTagInfo{FullMethodName: "/package.service/method"}
+	out := &stats.OutPayload{Length: 2000}
+	end := &stats.End{Error: nil}
+
+	if err := view.Register(ClientSentBytesPerRPCView); err != nil {
+		t.Error(err)
+	}
+	h := &ClientHandler{}
+	h.StartOptions.Sampler = trace.AlwaysSample()
+	ctx, err := tag.New(context.Background(), tag.Upsert(key, "test_val"))
+	if err != nil {
+		t.Error(err)
+	}
+	encoded := tag.Encode(tag.FromContext(ctx))
+	ctx = stats.SetTags(context.Background(), encoded)
+	ctx = h.TagRPC(ctx, tagInfo)
+
+	out.Client = true
+	h.HandleRPC(ctx, out)
+	end.Client = true
+	h.HandleRPC(ctx, end)
+
+	span := trace.FromContext(ctx)
+	if span == nil {
+		t.Fatal("expected non-nil span, got nil")
+	}
+	if !span.IsRecordingEvents() {
+		t.Errorf("span should be sampled")
+	}
+	attachments := map[string]interface{}{metricdata.AttachmentKeySpanContext: span.SpanContext()}
+	wantExemplar := &metricdata.Exemplar{Value: 2000, Attachments: attachments}
+
+	rows, err := view.RetrieveData(ClientSentBytesPerRPCView.Name)
+	if err != nil {
+		t.Fatal("Error RetrieveData ", err)
+	}
+	if len(rows) == 0 {
+		t.Fatal("No data was recorded.")
+	}
+	data := rows[0].Data
+	dis, ok := data.(*view.DistributionData)
+	if !ok {
+		t.Fatal("want DistributionData, got ", data)
+	}
+	// Only recorded value is 2000, which falls into the second bucket (1024, 2048].
+	wantBuckets := []int64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	if !reflect.DeepEqual(dis.CountPerBucket, wantBuckets) {
+		t.Errorf("want buckets %v, got %v", wantBuckets, dis.CountPerBucket)
+	}
+	for i, e := range dis.ExemplarsPerBucket {
+		// Only the second bucket should have an exemplar.
+		if i == 1 {
+			if diff := cmpExemplar(e, wantExemplar); diff != "" {
+				t.Fatalf("Unexpected Exemplar -got +want: %s", diff)
+			}
+		} else if e != nil {
+			t.Errorf("want nil exemplar, got %v", e)
+		}
+	}
+
+	// Unregister views to cleanup.
+	view.Unregister(ClientSentBytesPerRPCView)
+}
+
 // containsRow returns true if rows contain r.
 func containsRow(rows []*view.Row, r *view.Row) bool {
 	for _, x := range rows {
@@ -343,3 +414,8 @@ func containsRow(rows []*view.Row, r *view.Row) bool {
 	}
 	return false
 }
+
+// Compare exemplars while ignoring exemplar timestamp, since timestamp is non-deterministic.
+func cmpExemplar(got, want *metricdata.Exemplar) string {
+	return cmp.Diff(got, want, cmpopts.IgnoreFields(metricdata.Exemplar{}, "Timestamp"), cmpopts.IgnoreUnexported(metricdata.Exemplar{}))
+}
diff --git a/plugin/ocgrpc/server_stats_handler_test.go b/plugin/ocgrpc/server_stats_handler_test.go
index cab232a..921155e 100644
--- a/plugin/ocgrpc/server_stats_handler_test.go
+++ b/plugin/ocgrpc/server_stats_handler_test.go
@@ -16,11 +16,13 @@
 package ocgrpc
 
 import (
+	"reflect"
 	"testing"
 
 	"go.opencensus.io/trace"
 	"golang.org/x/net/context"
 
+	"go.opencensus.io/metric/metricdata"
 	"go.opencensus.io/stats/view"
 	"go.opencensus.io/tag"
 
@@ -334,3 +336,69 @@ func newDistributionData(countPerBucket []int64, count int64, min, max, mean, su
 		CountPerBucket:  countPerBucket,
 	}
 }
+
+func TestServerRecordExemplar(t *testing.T) {
+	key, _ := tag.NewKey("test_key")
+	tagInfo := &stats.RPCTagInfo{FullMethodName: "/package.service/method"}
+	out := &stats.OutPayload{Length: 2000}
+	end := &stats.End{Error: nil}
+
+	if err := view.Register(ServerSentBytesPerRPCView); err != nil {
+		t.Error(err)
+	}
+	h := &ServerHandler{}
+	h.StartOptions.Sampler = trace.AlwaysSample()
+	ctx, err := tag.New(context.Background(), tag.Upsert(key, "test_val"))
+	if err != nil {
+		t.Error(err)
+	}
+	encoded := tag.Encode(tag.FromContext(ctx))
+	ctx = stats.SetTags(context.Background(), encoded)
+	ctx = h.TagRPC(ctx, tagInfo)
+
+	out.Client = false
+	h.HandleRPC(ctx, out)
+	end.Client = false
+	h.HandleRPC(ctx, end)
+
+	span := trace.FromContext(ctx)
+	if span == nil {
+		t.Fatal("expected non-nil span, got nil")
+	}
+	if !span.IsRecordingEvents() {
+		t.Errorf("span should be sampled")
+	}
+	attachments := map[string]interface{}{metricdata.AttachmentKeySpanContext: span.SpanContext()}
+	wantExemplar := &metricdata.Exemplar{Value: 2000, Attachments: attachments}
+
+	rows, err := view.RetrieveData(ServerSentBytesPerRPCView.Name)
+	if err != nil {
+		t.Fatal("Error RetrieveData ", err)
+	}
+	if len(rows) == 0 {
+		t.Fatal("No data was recorded.")
+	}
+	data := rows[0].Data
+	dis, ok := data.(*view.DistributionData)
+	if !ok {
+		t.Fatal("want DistributionData, got ", data)
+	}
+	// Only recorded value is 2000, which falls into the second bucket (1024, 2048].
+	wantBuckets := []int64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	if !reflect.DeepEqual(dis.CountPerBucket, wantBuckets) {
+		t.Errorf("want buckets %v, got %v", wantBuckets, dis.CountPerBucket)
+	}
+	for i, e := range dis.ExemplarsPerBucket {
+		// Only the second bucket should have an exemplar.
+		if i == 1 {
+			if diff := cmpExemplar(e, wantExemplar); diff != "" {
+				t.Fatalf("Unexpected Exemplar -got +want: %s", diff)
+			}
+		} else if e != nil {
+			t.Errorf("want nil exemplar, got %v", e)
+		}
+	}
+
+	// Unregister views to cleanup.
+	view.Unregister(ServerSentBytesPerRPCView)
+}
diff --git a/tag/map_codec_test.go b/tag/map_codec_test.go
index a5605e6..344ab0e 100644
--- a/tag/map_codec_test.go
+++ b/tag/map_codec_test.go
@@ -91,7 +91,7 @@ func TestEncodeDecode(t *testing.T) {
 
 		got := make([]keyValue, 0)
 		for k, v := range decoded.m {
-			got = append(got, keyValue{k, string(v)})
+			got = append(got, keyValue{k, string(v.value)})
 		}
 		want := tc.pairs
 
diff --git a/tag/map_test.go b/tag/map_test.go
index 855b747..04471a8 100644
--- a/tag/map_test.go
+++ b/tag/map_test.go
@@ -23,6 +23,11 @@ import (
 	"testing"
 )
 
+var (
+	ttlUnlimitedPropMd = createMetadatas(WithTTL(TTLUnlimitedPropagation))
+	ttlNoPropMd        = createMetadatas(WithTTL(TTLNoPropagation))
+)
+
 func TestContext(t *testing.T) {
 	k1, _ := NewKey("k1")
 	k2, _ := NewKey("k2")
@@ -34,8 +39,8 @@ func TestContext(t *testing.T) {
 	)
 	got := FromContext(ctx)
 	want := newMap()
-	want.insert(k1, "v1")
-	want.insert(k2, "v2")
+	want.insert(k1, "v1", ttlUnlimitedPropMd)
+	want.insert(k2, "v2", ttlUnlimitedPropMd)
 
 	if !reflect.DeepEqual(got, want) {
 		t.Errorf("Map = %#v; want %#v", got, want)
@@ -52,8 +57,8 @@ func TestDo(t *testing.T) {
 	)
 	got := FromContext(ctx)
 	want := newMap()
-	want.insert(k1, "v1")
-	want.insert(k2, "v2")
+	want.insert(k1, "v1", ttlUnlimitedPropMd)
+	want.insert(k2, "v2", ttlUnlimitedPropMd)
 	Do(ctx, func(ctx context.Context) {
 		got = FromContext(ctx)
 	})
@@ -168,23 +173,175 @@ func TestNewMap(t *testing.T) {
 	}
 }
 
+func TestNewMapWithMetadata(t *testing.T) {
+	k3, _ := NewKey("k3")
+	k4, _ := NewKey("k4")
+	k5, _ := NewKey("k5")
+
+	tests := []struct {
+		name    string
+		initial *Map
+		mods    []Mutator
+		want    *Map
+	}{
+		{
+			name:    "from empty; insert",
+			initial: nil,
+			mods: []Mutator{
+				Insert(k5, "5", WithTTL(TTLNoPropagation)),
+				Insert(k4, "4"),
+			},
+			want: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlNoPropMd},
+				tagContent{"4", ttlUnlimitedPropMd}),
+		},
+		{
+			name:    "from existing; insert existing",
+			initial: makeTestTagMapWithMetadata(tagContent{"5", ttlNoPropMd}),
+			mods: []Mutator{
+				Insert(k5, "5", WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: makeTestTagMapWithMetadata(tagContent{"5", ttlNoPropMd}),
+		},
+		{
+			name:    "from existing; update non-existing",
+			initial: makeTestTagMapWithMetadata(tagContent{"5", ttlNoPropMd}),
+			mods: []Mutator{
+				Update(k4, "4", WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: makeTestTagMapWithMetadata(tagContent{"5", ttlNoPropMd}),
+		},
+		{
+			name: "from existing; update existing",
+			initial: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlUnlimitedPropMd},
+				tagContent{"4", ttlNoPropMd}),
+			mods: []Mutator{
+				Update(k5, "5"),
+				Update(k4, "4", WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlUnlimitedPropMd},
+				tagContent{"4", ttlUnlimitedPropMd}),
+		},
+		{
+			name: "from existing; upsert existing",
+			initial: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlNoPropMd},
+				tagContent{"4", ttlNoPropMd}),
+			mods: []Mutator{
+				Upsert(k4, "4", WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlNoPropMd},
+				tagContent{"4", ttlUnlimitedPropMd}),
+		},
+		{
+			name: "from existing; upsert non-existing",
+			initial: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlNoPropMd}),
+			mods: []Mutator{
+				Upsert(k4, "4", WithTTL(TTLUnlimitedPropagation)),
+				Upsert(k3, "3"),
+			},
+			want: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlNoPropMd},
+				tagContent{"4", ttlUnlimitedPropMd},
+				tagContent{"3", ttlUnlimitedPropMd}),
+		},
+		{
+			name: "from existing; delete",
+			initial: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlNoPropMd},
+				tagContent{"4", ttlNoPropMd}),
+			mods: []Mutator{
+				Delete(k5),
+			},
+			want: makeTestTagMapWithMetadata(
+				tagContent{"4", ttlNoPropMd}),
+		},
+		{
+			name:    "from non-existing; upsert with multiple-metadata",
+			initial: nil,
+			mods: []Mutator{
+				Upsert(k4, "4", WithTTL(TTLUnlimitedPropagation), WithTTL(TTLNoPropagation)),
+				Upsert(k5, "5", WithTTL(TTLNoPropagation), WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: makeTestTagMapWithMetadata(
+				tagContent{"4", ttlNoPropMd},
+				tagContent{"5", ttlUnlimitedPropMd}),
+		},
+		{
+			name:    "from non-existing; insert with multiple-metadata",
+			initial: nil,
+			mods: []Mutator{
+				Insert(k5, "5", WithTTL(TTLNoPropagation), WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlUnlimitedPropMd}),
+		},
+		{
+			name: "from existing; update with multiple-metadata",
+			initial: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlNoPropMd}),
+			mods: []Mutator{
+				Update(k5, "5", WithTTL(TTLNoPropagation), WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: makeTestTagMapWithMetadata(
+				tagContent{"5", ttlUnlimitedPropMd}),
+		},
+		{
+			name:    "from empty; update invalid",
+			initial: nil,
+			mods: []Mutator{
+				Insert(k4, "4\x19", WithTTL(TTLUnlimitedPropagation)),
+				Upsert(k4, "4\x19", WithTTL(TTLUnlimitedPropagation)),
+				Update(k4, "4\x19", WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: nil,
+		},
+		{
+			name:    "from empty; insert partial",
+			initial: nil,
+			mods: []Mutator{
+				Upsert(k3, "3", WithTTL(TTLUnlimitedPropagation)),
+				Upsert(k4, "4\x19", WithTTL(TTLUnlimitedPropagation)),
+			},
+			want: nil,
+		},
+	}
+
+	// Test api for insert, update, and upsert using metadata.
+	for _, tt := range tests {
+		ctx := NewContext(context.Background(), tt.initial)
+		ctx, err := New(ctx, tt.mods...)
+		if tt.want != nil && err != nil {
+			t.Errorf("%v: New = %v", tt.name, err)
+		}
+
+		if got, want := FromContext(ctx), tt.want; !reflect.DeepEqual(got, want) {
+			t.Errorf("%v: got %v; want %v", tt.name, got, want)
+		}
+	}
+}
+
 func TestNewValidation(t *testing.T) {
 	tests := []struct {
 		err  string
 		seed *Map
 	}{
 		// Key name validation in seed
-		{err: "invalid key", seed: &Map{m: map[Key]string{{name: ""}: "foo"}}},
-		{err: "", seed: &Map{m: map[Key]string{{name: "key"}: "foo"}}},
-		{err: "", seed: &Map{m: map[Key]string{{name: strings.Repeat("a", 255)}: "census"}}},
-		{err: "invalid key", seed: &Map{m: map[Key]string{{name: strings.Repeat("a", 256)}: "census"}}},
-		{err: "invalid key", seed: &Map{m: map[Key]string{{name: "Приве́т"}: "census"}}},
+		{err: "invalid key", seed: &Map{m: map[Key]tagContent{{name: ""}: {"foo", ttlNoPropMd}}}},
+		{err: "", seed: &Map{m: map[Key]tagContent{{name: "key"}: {"foo", ttlNoPropMd}}}},
+		{err: "", seed: &Map{m: map[Key]tagContent{{name: strings.Repeat("a", 255)}: {"census", ttlNoPropMd}}}},
+		{err: "invalid key", seed: &Map{m: map[Key]tagContent{{name: strings.Repeat("a", 256)}: {"census", ttlNoPropMd}}}},
+		{err: "invalid key", seed: &Map{m: map[Key]tagContent{{name: "Приве́т"}: {"census", ttlNoPropMd}}}},
 
 		// Value validation
-		{err: "", seed: &Map{m: map[Key]string{{name: "key"}: ""}}},
-		{err: "", seed: &Map{m: map[Key]string{{name: "key"}: strings.Repeat("a", 255)}}},
-		{err: "invalid value", seed: &Map{m: map[Key]string{{name: "key"}: "Приве́т"}}},
-		{err: "invalid value", seed: &Map{m: map[Key]string{{name: "key"}: strings.Repeat("a", 256)}}},
+		{err: "", seed: &Map{m: map[Key]tagContent{{name: "key"}: {"", ttlNoPropMd}}}},
+		{err: "", seed: &Map{m: map[Key]tagContent{{name: "key"}: {strings.Repeat("a", 255), ttlNoPropMd}}}},
+		{err: "invalid value", seed: &Map{m: map[Key]tagContent{{name: "key"}: {"Приве́т", ttlNoPropMd}}}},
+		{err: "invalid value", seed: &Map{m: map[Key]tagContent{{name: "key"}: {strings.Repeat("a", 256), ttlNoPropMd}}}},
 	}
 
 	for i, tt := range tests {
@@ -216,7 +373,16 @@ func makeTestTagMap(ids ...int) *Map {
 	m := newMap()
 	for _, v := range ids {
 		k, _ := NewKey(fmt.Sprintf("k%d", v))
-		m.m[k] = fmt.Sprintf("v%d", v)
+		m.m[k] = tagContent{fmt.Sprintf("v%d", v), ttlUnlimitedPropMd}
+	}
+	return m
+}
+
+func makeTestTagMapWithMetadata(tcs ...tagContent) *Map {
+	m := newMap()
+	for _, tc := range tcs {
+		k, _ := NewKey(fmt.Sprintf("k%s", tc.value))
+		m.m[k] = tc
 	}
 	return m
 }