func (e *traceExporter) uploadSpans(ctx context.Context, spans []*tracepb.Span) error {
	req := tracepb.BatchWriteSpansRequest{
		Name:  "projects/" + e.projectID,
		Spans: spans,
	}
	var cancel func()
	ctx, cancel = newContextWithTimeout(ctx, e.o.Timeout)
	defer cancel()
	err := e.client.BatchWriteSpans(ctx, &req)
	if err != nil {
		e.o.handleError(fmt.Errorf("failed to export to Google Cloud Monitoring: %w", err))
	}
	return err
}
uploadSpans sends a set of spans to Stackdriver.
package trace
import (
	"context"
	"fmt"
	"time"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	traceclient "cloud.google.com/go/trace/apiv2"
	"google.golang.org/api/option"
	tracepb "google.golang.org/genproto/googleapis/devtools/cloudtrace/v2"
)
type traceExporter struct {
	o         *options
	projectID string
	uploadFn func(ctx context.Context, spans []*tracepb.Span) error
	overflowLogger
	client *traceclient.Client
}
func newTraceExporter(o *options) (*traceExporter, error) {
	clientOps := append(o.TraceClientOptions, option.WithUserAgent(userAgent))
	client, err := traceclient.NewClient(o.Context, clientOps...)
	if err != nil {
		return nil, fmt.Errorf("stackdriver: couldn't initiate trace client: %v", err)
	}
	e := &traceExporter{
		projectID:      o.ProjectID,
		client:         client,
		o:              o,
		overflowLogger: overflowLogger{delayDur: 5 * time.Second},
	}
	e.uploadFn = e.uploadSpans
	return e, nil
}
func (e *traceExporter) ExportSpans(ctx context.Context, spanData []sdktrace.ReadOnlySpan) error {
	results := make([]*tracepb.Span, len(spanData))
	for i, sd := range spanData {
		results[i] = e.ConvertSpan(ctx, sd)
	}
	return e.uploadFn(ctx, results)
}
func (e *traceExporter) ConvertSpan(_ context.Context, sd sdktrace.ReadOnlySpan) *tracepb.Span {
	return protoFromReadOnlySpan(sd, e.projectID)
}
func (e *traceExporter) Shutdown(ctx context.Context) error {
	return e.client.Close()
}