func convertFromSum(edata exportData, sum aggregation.Sum) (prompb.TimeSeries, error) {
	value, err := sum.Sum()
	if err != nil {
		return prompb.TimeSeries{}, err
	}
	name := sanitize(edata.Descriptor().Name())
	numberKind := edata.Descriptor().NumberKind()
	tSeries := createTimeSeries(edata, value, numberKind, attribute.String("__name__", name))
	return tSeries, nil
}
convertFromSum returns a single TimeSeries based on a Record with a Sum aggregation
package cortex
import (
	"bytes"
	"context"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"time"
	"github.com/golang/snappy"
	"github.com/prometheus/prometheus/prompb"
	"go.opentelemetry.io/otel/attribute"
	apimetric "go.opentelemetry.io/otel/metric"
	"go.opentelemetry.io/otel/metric/global"
	"go.opentelemetry.io/otel/metric/number"
	"go.opentelemetry.io/otel/sdk/export/metric"
	export "go.opentelemetry.io/otel/sdk/export/metric"
	"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
	"go.opentelemetry.io/otel/sdk/instrumentation"
	"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
	controller "go.opentelemetry.io/otel/sdk/metric/controller/basic"
	processor "go.opentelemetry.io/otel/sdk/metric/processor/basic"
	"go.opentelemetry.io/otel/sdk/metric/selector/simple"
	"go.opentelemetry.io/otel/sdk/resource"
)
type Exporter struct {
	config Config
}
type exportData struct {
	export.Record
	Resource *resource.Resource
}
func (e *Exporter) ExportKindFor(*apimetric.Descriptor, aggregation.Kind) metric.ExportKind {
	return metric.CumulativeExportKind
}
func (e *Exporter) Export(_ context.Context, res *resource.Resource, checkpointSet metric.InstrumentationLibraryReader) error {
	timeseries, err := e.ConvertToTimeSeries(res, checkpointSet)
	if err != nil {
		return err
	}
	message, buildMessageErr := e.buildMessage(timeseries)
	if buildMessageErr != nil {
		return buildMessageErr
	}
	request, buildRequestErr := e.buildRequest(message)
	if buildRequestErr != nil {
		return buildRequestErr
	}
	sendRequestErr := e.sendRequest(request)
	if sendRequestErr != nil {
		return sendRequestErr
	}
	return nil
}
func NewRawExporter(config Config) (*Exporter, error) {
	if err := config.Validate(); err != nil {
		return nil, err
	}
	exporter := Exporter{config}
	return &exporter, nil
}
func NewExportPipeline(config Config, options ...controller.Option) (*controller.Controller, error) {
	exporter, err := NewRawExporter(config)
	if err != nil {
		return nil, err
	}
	cont := controller.New(
		processor.NewFactory(
			simple.NewWithHistogramDistribution(
				histogram.WithExplicitBoundaries(config.HistogramBoundaries),
			),
			exporter,
		),
		append(options, controller.WithExporter(exporter))...,
	)
	return cont, cont.Start(context.TODO())
}
func InstallNewPipeline(config Config, options ...controller.Option) (*controller.Controller, error) {
	cont, err := NewExportPipeline(config, options...)
	if err != nil {
		return nil, err
	}
	global.SetMeterProvider(cont)
	return cont, nil
}
func (e *Exporter) ConvertToTimeSeries(res *resource.Resource, checkpointSet export.InstrumentationLibraryReader) ([]prompb.TimeSeries, error) {
	var aggError error
	var timeSeries []prompb.TimeSeries
	aggError = checkpointSet.ForEach(func(library instrumentation.Library, reader export.Reader) error {
		return reader.ForEach(e, func(record metric.Record) error {
			edata := exportData{
				Resource: res,
				Record:   record,
			}
			agg := record.Aggregation()
			if histogram, ok := agg.(aggregation.Histogram); ok {
				tSeries, err := convertFromHistogram(edata, histogram)
				if err != nil {
					return err
				}
				timeSeries = append(timeSeries, tSeries...)
			} else if sum, ok := agg.(aggregation.Sum); ok {
				tSeries, err := convertFromSum(edata, sum)
				if err != nil {
					return err
				}
				timeSeries = append(timeSeries, tSeries)
				if minMaxSumCount, ok := agg.(aggregation.MinMaxSumCount); ok {
					tSeries, err := convertFromMinMaxSumCount(edata, minMaxSumCount)
					if err != nil {
						return err
					}
					timeSeries = append(timeSeries, tSeries...)
				}
			} else if lastValue, ok := agg.(aggregation.LastValue); ok {
				tSeries, err := convertFromLastValue(edata, lastValue)
				if err != nil {
					return err
				}
				timeSeries = append(timeSeries, tSeries)
			} else {
				fmt.Printf("No conversion found for record: %s\n", edata.Descriptor().Name())
			}
			return nil
		})
	})
	if aggError != nil {
		return nil, aggError
	}
	return timeSeries, nil
}
func createTimeSeries(edata exportData, value number.Number, valueNumberKind number.Kind, extraAttributes ...attribute.KeyValue) prompb.TimeSeries {
	sample := prompb.Sample{
		Value:     value.CoerceToFloat64(valueNumberKind),
		Timestamp: int64(time.Nanosecond) * edata.EndTime().UnixNano() / int64(time.Millisecond),
	}
	attributes := createLabelSet(edata, extraAttributes...)
	return prompb.TimeSeries{
		Samples: []prompb.Sample{sample},
		Labels:  attributes,
	}
}