// Copyright (c) 2019 The Jaeger Authors. // Copyright (c) 2017 Uber Technologies, Inc. // // 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 model import ( "sort" ) type byTraceID []*TraceID func (s byTraceID) Len() int { return len(s) } func (s byTraceID) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s byTraceID) Less(i, j int) bool { if s[i].High < s[j].High { return true } else if s[i].High > s[j].High { return false } return s[i].Low < s[j].Low } // SortTraceIDs sorts a list of TraceIDs func SortTraceIDs(traceIDs []*TraceID) { sort.Sort(byTraceID(traceIDs)) } type traceByTraceID []*Trace func (s traceByTraceID) Len() int { return len(s) } func (s traceByTraceID) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s traceByTraceID) Less(i, j int) bool { switch { case len(s[i].Spans) == 0: return true case len(s[j].Spans) == 0: return false default: return s[i].Spans[0].TraceID.Low < s[j].Spans[0].TraceID.Low } } // SortTraces deep sorts a list of traces by TraceID. func SortTraces(traces []*Trace) { sort.Sort(traceByTraceID(traces)) for _, trace := range traces { SortTrace(trace) } } type spanBySpanID []*Span func (s spanBySpanID) Len() int { return len(s) } func (s spanBySpanID) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s spanBySpanID) Less(i, j int) bool { return s[i].SpanID < s[j].SpanID } // SortTrace deep sorts a trace's spans by SpanID. func SortTrace(trace *Trace) { sort.Sort(spanBySpanID(trace.Spans)) for _, span := range trace.Spans { SortSpan(span) } } // SortSpan deep sorts a span: this sorts its tags, logs by timestamp, tags in logs, and tags in process. func SortSpan(span *Span) { span.NormalizeTimestamps() sortTags(span.Tags) sortLogs(span.Logs) sortProcess(span.Process) } type tagByKey []KeyValue func (t tagByKey) Len() int { return len(t) } func (t tagByKey) Swap(i, j int) { t[i], t[j] = t[j], t[i] } func (t tagByKey) Less(i, j int) bool { return t[i].Key < t[j].Key } func sortTags(tags []KeyValue) { sort.Sort(tagByKey(tags)) } type logByTimestamp []Log func (t logByTimestamp) Len() int { return len(t) } func (t logByTimestamp) Swap(i, j int) { t[i], t[j] = t[j], t[i] } func (t logByTimestamp) Less(i, j int) bool { return t[i].Timestamp.Before(t[j].Timestamp) } func sortLogs(logs []Log) { sort.Sort(logByTimestamp(logs)) for _, log := range logs { sortTags(log.Fields) } } func sortProcess(process *Process) { if process != nil { sortTags(process.Tags) } }