import { css, cx } from '@emotion/css'; import { PureComponent } from 'react'; import { MetadataInspectorProps, rangeUtil } from '@grafana/data'; import { stylesFactory } from '@grafana/ui'; import { config } from 'app/core/config'; import { GraphiteDatasource } from '../datasource'; import { getRollupNotice, getRuntimeConsolidationNotice, parseSchemaRetentions } from '../meta'; import { GraphiteOptions, GraphiteQuery, MetricTankSeriesMeta } from '../types'; export type Props = MetadataInspectorProps; export interface State { index: number; } export class MetricTankMetaInspector extends PureComponent { renderMeta(meta: MetricTankSeriesMeta, key: string) { const styles = getStyles(); const buckets = parseSchemaRetentions(meta['schema-retentions']); const rollupNotice = getRollupNotice([meta]); const runtimeNotice = getRuntimeConsolidationNotice([meta]); const normFunc = (meta['consolidator-normfetch'] ?? '').replace('Consolidator', ''); const totalSeconds = buckets.reduce( (acc, bucket) => acc + (bucket.retention ? rangeUtil.intervalToSeconds(bucket.retention) : 0), 0 ); return (
Schema: {meta['schema-name']}
Series count: {meta.count}
Step 1: Fetch
First data is fetched, either from raw data archive or a rollup archive
{rollupNotice &&

{rollupNotice.text}

} {!rollupNotice &&

No rollup archive was used

}
{buckets.map((bucket, index) => { const bucketLength = bucket.retention ? rangeUtil.intervalToSeconds(bucket.retention) : 0; const lengthPercent = (bucketLength / totalSeconds) * 100; const isActive = index === meta['archive-read']; return (
{bucket.interval}
{bucket.retention}
); })}
Step 2: Normalization
Normalization happens when series with different intervals between points are combined.
{meta['aggnum-norm'] > 1 &&

Normalization did occur using {normFunc}

} {meta['aggnum-norm'] === 1 &&

No normalization was needed

}
Step 3: Runtime consolidation
If there are too many data points at this point Metrictank will consolidate them down to below max data points (set in queries tab).
{runtimeNotice &&

{runtimeNotice.text}

} {!runtimeNotice &&

No runtime consolidation

}
); } render() { const { data } = this.props; // away to dedupe them const seriesMetas: Record = {}; for (const series of data) { const seriesMetaList: MetricTankSeriesMeta[] | undefined = series?.meta?.custom?.seriesMetaList; if (seriesMetaList) { for (const metaItem of seriesMetaList) { // key is to dedupe as many series will have identitical meta const key = `${JSON.stringify(metaItem)}`; if (seriesMetas[key]) { seriesMetas[key].count += metaItem.count; } else { seriesMetas[key] = metaItem; } } } } if (Object.keys(seriesMetas).length === 0) { return
No response meta data
; } return (

Metrictank Lineage

{Object.keys(seriesMetas).map((key) => this.renderMeta(seriesMetas[key], key))}
); } } const getStyles = stylesFactory(() => { const { theme } = config; const borderColor = theme.isDark ? theme.palette.gray25 : theme.palette.gray85; const background = theme.isDark ? theme.palette.dark1 : theme.palette.white; const headerBg = theme.isDark ? theme.palette.gray15 : theme.palette.gray85; return { metaItem: css({ background: background, border: `1px solid ${borderColor}`, marginBottom: theme.spacing.md, }), metaItemHeader: css({ background: headerBg, padding: `${theme.spacing.xs} ${theme.spacing.md}`, fontSize: theme.typography.size.md, display: 'flex', justifyContent: 'space-between', }), metaItemBody: css({ padding: theme.spacing.md, }), stepHeading: css({ fontSize: theme.typography.size.md, }), stepDescription: css({ fontSize: theme.typography.size.sm, color: theme.colors.textWeak, marginBottom: theme.spacing.sm, }), step: css({ marginBottom: theme.spacing.lg, '&:last-child': { marginBottom: 0, }, }), bucket: css({ display: 'flex', marginBottom: theme.spacing.sm, borderRadius: theme.border.radius.sm, }), bucketInterval: css({ flexGrow: 0, width: '60px', }), bucketRetention: css({ background: `linear-gradient(0deg, ${theme.palette.blue85}, ${theme.palette.blue95})`, textAlign: 'center', color: theme.palette.white, marginRight: theme.spacing.md, borderRadius: theme.border.radius.sm, }), bucketRetentionActive: css({ background: `linear-gradient(0deg, ${theme.palette.greenBase}, ${theme.palette.greenShade})`, }), }; });