func TraceFromInfluxQLRow(row *models.Row) (*model.Trace, error) {
	var errs []error
	var traceID model.TraceID
	var err error
	for k, v := range row.Tags {
		if k == common.TraceIDKey {
			traceID, err = model.TraceIDFromString(v)
			if err != nil {
				errs = append(errs, err)
			}
			break
		}
	}
	if traceID.High == 0 && traceID.Low == 0 {
		errs = append(errs, errors.New("trace_id tag not found"))
	}
	timeColI, serviceNameColI, operationNameColI, spanIDColI, durationColI, flagsColI, processTagKeysColI, referencesColI :=
		-1, -1, -1, -1, -1, -1, -1, -1
	jaegerTagKeysByColI := make(map[int]string)
	for colI, col := range row.Columns {
		switch col {
		case common.TimeV1Key:
			timeColI = colI
		case common.ServiceNameKey:
			serviceNameColI = colI
		case common.OperationNameKey:
			operationNameColI = colI
		case common.SpanIDKey:
			spanIDColI = colI
		case common.DurationKey:
			durationColI = colI
		case common.FlagsKey:
			flagsColI = colI
		case common.ProcessTagKeysKey:
			processTagKeysColI = colI
		case common.ReferencesKey:
			referencesColI = colI
		default:
			jaegerTagKeysByColI[colI] = col
		}
	}
	if len(errs) > 0 {
		return nil, multierror.Wrap(errs)
	}
	var trace model.Trace
	for _, v := range row.Values {
		if timeColI == -1 {
			errs = append(errs, errors.New("time column not found"))
			continue
		}
		startTime, err := time.Parse(time.RFC3339Nano, v[timeColI].(string))
		if err != nil {
			errs = append(errs, err)
			continue
		}
		startTime = removeSpanIDFromTime(startTime.UnixNano())
		if spanIDColI == -1 {
			errs = append(errs, errors.New("span_id column not found"))
			continue
		}
		spanID, err := model.SpanIDFromString(v[spanIDColI].(string))
		if err != nil {
			errs = append(errs, err)
			continue
		}
		var references []model.SpanRef
		if referencesColI != -1 && v[referencesColI] != nil {
			references, err = referencesFromString(v[referencesColI].(string))
			if err != nil {
				errs = append(errs, errors.WithMessagef(err, "invalid reference '%s'", v[referencesColI].(string)))
				continue
			}
			for i := range references {
				references[i].TraceID = traceID
			}
		}
		if serviceNameColI == -1 {
			errs = append(errs, errors.New("service_name column not found"))
			continue
		}
		process := &model.Process{
			ServiceName: v[serviceNameColI].(string),
		}
		processTagKeys := make(map[string]struct{})
		if processTagKeysColI != -1 && v[processTagKeysColI] != nil {
			for _, k := range strings.Split(v[processTagKeysColI].(string), ",") {
				processTagKeys[k] = struct{}{}
			}
		}
		var tags []model.KeyValue
		for colI, key := range jaegerTagKeysByColI {
			if v[colI] == nil {
				continue
			}
			keyValue, err := stringsToKeyValue(key, v[colI].(string))
			if err != nil {
				errs = append(errs, err)
				continue
			}
			if _, found := processTagKeys[key]; found {
				process.Tags = append(process.Tags, *keyValue)
			} else {
				tags = append(tags, *keyValue)
			}
		}
		var flags model.Flags
		if flagsColI != -1 && v[flagsColI] != nil {
			value, err := v[flagsColI].(json.Number).Int64()
			if err != nil {
				errs = append(errs, err)
				continue
			}
			flags = model.Flags(value)
		}
		var duration time.Duration
		if durationColI != -1 && v[durationColI] != nil {
			value, err := v[durationColI].(json.Number).Int64()
			if err != nil {
				errs = append(errs, err)
				continue
			}
			duration = time.Duration(value)
		}
		if operationNameColI == -1 {
			errs = append(errs, errors.New("operation_name column not found"))
			continue
		}
		operationName := v[operationNameColI].(string)
		span := &model.Span{
			TraceID:       traceID,
			SpanID:        spanID,
			OperationName: operationName,
			References:    references,
			Flags:         flags,
			StartTime:     startTime,
			Duration:      duration,
			Tags:          tags,
			Process:       process,
			Logs:          nil,  
		}
		trace.Spans = append(trace.Spans, span)
	}
	if len(errs) > 0 {
		return nil, multierror.Wrap(errs)
	}
	return &trace, nil
}
TraceFromInfluxQLRow converts an InfluxQL result row to Jaeger traces.
package dbmodel
import (
	"encoding/base64"
	"encoding/json"
	"reflect"
	"strings"
	"time"
	client "github.com/influxdata/influxdb1-client"
	"github.com/influxdata/influxdb1-client/models"
	"github.com/influxdata/jaeger-influxdb/common"
	"github.com/jaegertracing/jaeger/model"
	"github.com/jaegertracing/jaeger/pkg/multierror"
	"github.com/pkg/errors"
)
func DependencyLinksFromResultV1(response *client.Response) ([]model.DependencyLink, error) {
	parentByChild := make(map[model.SpanID]model.SpanID)
	serviceNameBySpanID := make(map[model.SpanID]string)
	for _, result := range response.Results {
		if result.Err != nil {
			return nil, result.Err
		}
		for _, row := range result.Series {
			spanColI, serviceNameColI, referencesColI := -1, -1, -1
			for i, c := range row.Columns {
				switch c {
				case common.SpanIDKey:
					spanColI = i
				case common.ServiceNameKey:
					serviceNameColI = i
				case common.ReferencesKey:
					referencesColI = i
				}
			}
			for _, v := range row.Values {
				spanID, err := model.SpanIDFromString(v[spanColI].(string))
				if err != nil {
					return nil, errors.WithMessagef(err, "failed to parse SpanID '%s'", v[spanColI].(string))
				}
				serviceName := v[serviceNameColI].(string)
				serviceNameBySpanID[spanID] = serviceName
				var references string
				if referencesColI >= 0 && v[referencesColI] != nil {
					references = v[referencesColI].(string)
				}
				refs, err := referencesFromString(references)
				if err != nil {
					return nil, errors.WithMessagef(err, "failed to parse references '%s'", references)
				}
				for _, ref := range refs {
					if ref.RefType == model.SpanRefType_CHILD_OF {
						parentByChild[spanID] = ref.SpanID
					}
				}
			}
		}
	}
	m := make(map[string]*model.DependencyLink)
	for child, parent := range parentByChild {
		dl := m[child.String()+parent.String()]
		if dl == nil {
			dl = &model.DependencyLink{
				Parent:    serviceNameBySpanID[parent],
				Child:     serviceNameBySpanID[child],
				CallCount: 0,
			}
			m[child.String()+parent.String()] = dl
		}
		dl.CallCount++
	}
	dependencyLinks := make([]model.DependencyLink, 0, len(m))
	for _, dl := range m {
		if dl.Parent == dl.Child {
			continue
		}
		dependencyLinks = append(dependencyLinks, *dl)
	}
	return dependencyLinks, nil
}
func TraceIDsFromInfluxQLResult(response *client.Response) ([]model.TraceID, error) {
	var traceIDs []model.TraceID
	for _, result := range response.Results {
		if result.Err != nil {
			return nil, result.Err
		}
		for _, row := range result.Series {
			traceColI := -1
			for i, c := range row.Columns {
				switch c {
				case common.TraceIDKey:
					traceColI = i
				}
			}
			if traceIDs == nil {
				traceIDs = make([]model.TraceID, 0, len(row.Values))
			}
			for _, v := range row.Values {
				traceID, err := model.TraceIDFromString(v[traceColI].(string))
				if err != nil {
					return nil, errors.WithMessagef(err, "failed to get traceID from flux value '%s'", v[traceColI].(string))
				}
				traceIDs = append(traceIDs, traceID)
			}
		}
	}
	return traceIDs, nil
}
func TracesFromInfluxQLResponse(response *client.Response) ([]*model.Trace, error) {
	var traces []*model.Trace
	for _, result := range response.Results {
		for _, row := range result.Series {
			trace, err := TraceFromInfluxQLRow(&row)
			if err != nil {
				return nil, err
			}
			traces = append(traces, trace)
		}
	}
	return traces, nil
}