+ Select a field first +
++ Waiting +
+${service}
${message}
`, + ...styleOptions, + }; + }); + const edges: Array<{ from: number; to: number; color: string }> = []; + Object.keys(map).map((service) => { + map[service].targetServices.map((target) => { + edges.push({ + from: map[service].id, + to: map[target].id, + color: + relatedServices!.indexOf(service) >= 0 && relatedServices!.indexOf(target) >= 0 + ? 'rgba(0, 0, 0, 1)' + : 'rgba(0, 0, 0, 0.3)', + }); + }); + }); + return { graph: { nodes, edges } }; +} + +// returns flattened targetResource as an array for all traceGroups +export function getServiceMapTargetResources(map: ServiceObject, serviceName: string) { + return ([] as string[]).concat.apply( + [], + [...map[serviceName].traceGroups.map((traceGroup) => [...traceGroup.targetResource])] + ); +} + +export function calculateTicks(min: number, max: number, numTicks = 5): number[] { + if (min >= max) return calculateTicks(0, Math.max(1, max), numTicks); + min = Math.floor(min); + max = Math.ceil(max); + + const range = max - min; + const minInterval = range / numTicks; + const magnitude = Math.pow(10, Math.floor(Math.log10(minInterval))); + const residue = Math.ceil(minInterval / magnitude); + + let tick = magnitude; + if (residue > 5) tick *= 10; + else if (residue > 2) tick *= 5; + else if (residue > 1) tick *= 2; + + let curr = Math.max(0, Math.floor((min - 1) / tick) * tick); + const ticks = [curr]; + while (curr < max) { + curr += tick; + ticks.push(curr); + } + + return ticks; +} + +// calculates the minimum fixed_interval for date_histogram from time filter +export const minFixedInterval = (startTime: string, endTime: string) => { + if (startTime?.length === 0 || endTime?.length === 0 || startTime === endTime) return '1d'; + const momentStart = dateMath.parse(startTime)!; + const momentEnd = dateMath.parse(endTime)!; + const diffSeconds = momentEnd.unix() - momentStart.unix(); + + if (diffSeconds <= 1) return '1ms'; // less than 1 second + if (diffSeconds <= 60 * 2) return '1s'; // less than 2 minutes + if (diffSeconds <= 3600 * 2) return '1m'; // less than 2 hours + if (diffSeconds <= 86400 * 2) return '1h'; // less than 2 days + if (diffSeconds <= 86400 * 62) return '1d'; // less than 2 months + if (diffSeconds <= 86400 * 366) return '30d'; // less than 1 year + return '365d'; +}; + +export const fixedIntervalToMilli = (fixedInterval: string) => { + return { + '1ms': 1, + '1s': 1000, + '1m': 60000, + '1h': 3600000, + '1d': 86400000, + '30d': 86400000 * 30, + '365d': 86400000 * 365, + }[fixedInterval]; +}; + +export const fixedIntervalToTickFormat = (fixedInterval: string) => { + if (fixedInterval === '1d') return '%b %e, %Y'; + if (fixedInterval === '30d') return '%b %Y'; + if (fixedInterval === '365d') return '%Y'; + return ''; +}; + +export const getPercentileFilter = ( + percentileMaps: Array<{ traceGroupName: string; durationFilter: { gte?: number; lte?: number } }>, + conditionString: string // >= 95th, < 95th +): FilterType => { + const DSL: any = { + query: { + bool: { + must: [], + filter: [], + should: [], + must_not: [], + minimum_should_match: 1, + }, + }, + }; + percentileMaps.forEach((map) => { + DSL.query.bool.should.push({ + bool: { + must: [ + { + term: { + traceGroup: { + value: map.traceGroupName, + }, + }, + }, + { + range: { + 'traceGroupFields.durationInNanos': map.durationFilter, + }, + }, + ], + }, + }); + }); + return { + field: 'Latency percentile within trace group', + operator: '', + value: conditionString, + inverted: false, + disabled: false, + custom: DSL, + }; +}; + +export const filtersToDsl = ( + filters: FilterType[], + query: string, + startTime: string, + endTime: string +) => { + const DSL: any = { + query: { + bool: { + must: [], + filter: [], + should: [], + must_not: [], + }, + }, + custom: { + timeFilter: [], + serviceNames: [], + serviceNamesExclude: [], + traceGroup: [], + traceGroupExclude: [], + percentiles: { + query: { + bool: { + should: [], + }, + }, + }, + }, + }; + const timeFilter = { + range: { + startTime: { + gte: startTime, + lte: endTime, + }, + }, + }; + DSL.query.bool.must.push(timeFilter); + DSL.custom.timeFilter.push(timeFilter); + if (query.length > 0) { + DSL.query.bool.must.push({ + query_string: { + query, + }, + }); + } + + filters + .filter((filter) => !filter.disabled && !filter.locked) + .forEach((filter) => { + if (filter.custom?.query) { + // add percentile filter + DSL.query.bool.should.push(...filter.custom.query.bool.should); + DSL.custom.percentiles.query.bool.should.push(...filter.custom.query.bool.should); + DSL.query.bool.minimum_should_match = filter.custom.query.bool.minimum_should_match; + DSL.custom.percentiles.query.bool.minimum_should_match = + filter.custom.query.bool.minimum_should_match; + return; + } + + let filterQuery = {}; + let field = filter.field; + if (field === 'latency') field = 'traceGroupFields.durationInNanos'; + else if (field === 'error') field = 'traceGroupFields.statusCode'; + let value; + + switch (filter.operator) { + case 'exists': + case 'does not exist': + filterQuery = { + exists: { + field, + }, + }; + break; + + case 'is': + case 'is not': + value = filter.value; + // latency and error are not actual fields, need to convert first + if (field === 'traceGroupFields.durationInNanos') { + value = milliToNanoSec(value); + } else if (field === 'traceGroupFields.statusCode') { + value = value[0].label === 'true' ? '2' : '0'; + } + + filterQuery = { + term: { + [field]: value, + }, + }; + break; + + case 'is between': + case 'is not between': + const range: { gte?: string; lte?: string } = {}; + if (!filter.value.from.includes('\u221E')) range.gte = filter.value.from; + if (!filter.value.to.includes('\u221E')) range.lte = filter.value.to; + if (field === 'traceGroupFields.durationInNanos') { + if (range.lte) range.lte = milliToNanoSec(parseInt(range.lte || '')).toString(); + if (range.gte) range.gte = milliToNanoSec(parseInt(range.gte || '')).toString(); + } + filterQuery = { + range: { + [field]: range, + }, + }; + break; + + default: + break; + } + DSL.query.bool[filter.inverted ? 'must_not' : 'must'].push(filterQuery); + }); + + return DSL; +}; diff --git a/public/components/trace_analytics/components/common/plots/__tests__/__snapshots__/box_plt.test.tsx.snap b/public/components/trace_analytics/components/common/plots/__tests__/__snapshots__/box_plt.test.tsx.snap new file mode 100644 index 000000000..7d7595e66 --- /dev/null +++ b/public/components/trace_analytics/components/common/plots/__tests__/__snapshots__/box_plt.test.tsx.snap @@ -0,0 +1,169 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Box plot component renders box plot 1`] = ` ++ Latency <95 percentile +
++ 20ms - 50ms +
++ Latency >=95 percentile +
++ 50ms - 80ms +
+Latency <95 percentile
+{`${Math.round(plotParams.left)}ms - ${Math.round(plotParams.mid)}ms`}
+Latency >=95 percentile
+{`${Math.round(plotParams.mid)}ms - ${Math.round(plotParams.right)}ms`}
++ + | ++ + | ++ + | +
+
+
+
+ 24-hour latency trend
+
+
+
+ Â
+
+
+ |
+ + + | ++ + | +
---|---|---|---|---|---|
+
+
+
+ Trace group name
+
+
+
+ Â
+
+
+
+
+ |
+
+
+
+
+
+
+ 0Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 100Â Â Â Â Â Â Â Â Â Â Â Â 200Â Â Â Â Â Â Â Â Â Â Â Â 300Â Â Â Â Â Â Â Â Â Â Â Â 400
+
+
+
+ + Latency <95 percentile + ++ 26ms - 325ms + ++ Latency >=95 percentile + ++ 325ms - 325ms + + |
+
+
+
+
+ Average latency (ms)
+
+
+
+ Â
+
+
+
+ 187.27
+
+ |
+
+
+
+
+ 24-hour latency trend
+
+
+
+ Â
+
+
+
+ -
+
+ |
+
+
+
+
+ Error rate
+
+
+
+ Â
+
+
+
+
+
+ 14.29%
+
+ |
+
+
+
+
+ Traces
+
+
+
+ Â
+
+
+
+
+ |
+
+ + | ++ + | ++ + | ++ + | ++ + | ++ + | ++ + | +
---|---|---|---|---|---|---|
+
+ Name
+
+
+
+ |
+
+
+ Average latency (ms)
+
+
+ 49.54
+
+ |
+
+
+ Error rate
+
+
+
+
+ 3.77%
+
+ |
+
+
+ Throughput
+
+
+
+ |
+
+
+ No. of connected services
+
+
+ 2
+
+ |
+
+
+ Connected services
+
+
+
+
+ order, inventory
+
+ |
+
+
+ Traces
+
+
+
+ |
+
+ + | ++ + | ++ + | ++ + | ++ + | ++ + | +
---|---|---|---|---|---|
+
+ Trace ID
+
+
+
+ |
+
+
+ Trace group
+
+
+
+
+ HTTP GET
+
+ |
+
+
+ Latency (ms)
+
+
+
+ 19.91
+
+
+ |
+
+
+
+
+ Percentile in trace group
+
+
+
+
+ 30th
+
+ |
+
+
+ Errors
+
+
+ No
+
+ |
+
+
+ Last updated
+
+
+ 11/10/2020 09:55:45
+
+ |
+