github.com/thanos-io/thanos@v0.32.5/pkg/ui/react-app/src/thanos/pages/blocks/helpers.ts (about)

     1  import { LabelSet, Block, BlocksPool } from './block';
     2  import { Fuzzy, FuzzyResult } from '@nexucis/fuzzy';
     3  
     4  const stringify = (map: LabelSet): string => {
     5    let t = '';
     6    for (const [key, value] of Object.entries(map)) {
     7      t += `${key}: ${value} `;
     8    }
     9    return t;
    10  };
    11  
    12  export const isOverlapping = (a: Block, b: Block): boolean => {
    13    if (a?.minTime <= b?.minTime) return b?.minTime < a?.maxTime;
    14    else return a?.minTime < b?.maxTime;
    15  };
    16  
    17  const determineRow = (block: Block, rows: Block[][], startWithRow: number): number => {
    18    if (rows.length === 0) return 0;
    19  
    20    const len = rows[startWithRow]?.length || 0;
    21    if (len === 0) return startWithRow;
    22  
    23    if (isOverlapping(rows[startWithRow][len - 1], block)) {
    24      // Blocks are overlapping, try next row.
    25      return determineRow(block, rows, startWithRow + 1);
    26    }
    27    return startWithRow;
    28  };
    29  
    30  const splitOverlappingBlocks = (blocks: Block[]): Block[][] => {
    31    const rows: Block[][] = [[]];
    32    if (blocks.length === 0) return rows;
    33  
    34    blocks.forEach((b) => {
    35      const r = determineRow(b, rows, 0);
    36      if (!rows[r]) rows[r] = [];
    37      rows[r].push(b);
    38    });
    39    return rows;
    40  };
    41  
    42  const sortBlocksInRows = (blocks: Block[], findOverlappingBlocks: boolean): BlocksPool => {
    43    const poolWithOverlaps: { [key: string]: Block[] } = {};
    44  
    45    blocks
    46      .sort((a, b) => {
    47        if (a.compaction.level - b.compaction.level) {
    48          return a.compaction.level - b.compaction.level;
    49        }
    50        if (a.thanos.downsample.resolution - b.thanos.downsample.resolution) {
    51          return a.thanos.downsample.resolution - b.thanos.downsample.resolution;
    52        }
    53        return a.minTime - b.minTime;
    54      })
    55      .forEach((b) => {
    56        const key = `${b.compaction.level}-${b.thanos.downsample.resolution}`;
    57        if (!poolWithOverlaps[key]) poolWithOverlaps[key] = [];
    58  
    59        poolWithOverlaps[key].push(b);
    60      });
    61  
    62    const pool: BlocksPool = {};
    63  
    64    Object.entries(poolWithOverlaps).forEach(([key, blks]) => {
    65      if (findOverlappingBlocks) {
    66        let maxTime = 0;
    67        const filteredOverlap = blks.filter((value, index) => {
    68          const isOverlap = maxTime > value.minTime;
    69          if (value.maxTime > maxTime) {
    70            maxTime = value.maxTime;
    71          }
    72          return isOverlap || isOverlapping(blks[index], blks[index + 1]);
    73        });
    74        pool[key] = splitOverlappingBlocks(filteredOverlap);
    75      } else {
    76        pool[key] = splitOverlappingBlocks(blks);
    77      }
    78    });
    79  
    80    return pool;
    81  };
    82  
    83  export const sortBlocks = (
    84    blocks: Block[],
    85    label: string,
    86    findOverlappingBlocks: boolean
    87  ): { [source: string]: BlocksPool } => {
    88    const titles: { [key: string]: string } = {};
    89    const pool: { [key: string]: Block[] } = {};
    90  
    91    blocks
    92      .sort((a, b) => a.compaction.level - b.compaction.level)
    93      .forEach((b) => {
    94        const title = (function (): string {
    95          const key = label !== '' && b.thanos.labels[label];
    96  
    97          if (key) {
    98            return key;
    99          } else {
   100            let t = titles[stringify(b.thanos.labels)];
   101            if (t === undefined) {
   102              t = String(Object.keys(titles).length + 1);
   103              titles[stringify(b.thanos.labels)] = t;
   104            }
   105            return t;
   106          }
   107        })();
   108  
   109        pool[title] = pool[title] ? pool[title].concat([b]) : [b];
   110      });
   111  
   112    const sortedPool: { [source: string]: BlocksPool } = {};
   113    Object.keys(pool).forEach((k) => {
   114      sortedPool[k] = sortBlocksInRows(pool[k], findOverlappingBlocks);
   115    });
   116    return sortedPool;
   117  };
   118  
   119  export const download = (blob: Block): string => {
   120    const url = window.URL.createObjectURL(new Blob([JSON.stringify(blob, null, 2)], { type: 'application/json' }));
   121  
   122    return url;
   123  };
   124  
   125  export const getBlockByUlid = (blocks: Block[], ulid: string): Block[] => {
   126    if (ulid === '') {
   127      return blocks;
   128    }
   129  
   130    const ulidArray = blocks.map((block) => block.ulid);
   131    const fuz = new Fuzzy({ caseSensitive: true });
   132  
   133    const result: FuzzyResult[] = fuz.filter(ulid, ulidArray);
   134  
   135    const resultIndex = result.map((value) => value.index);
   136  
   137    const blockResult = blocks.filter((block, index) => resultIndex.includes(index));
   138    return blockResult;
   139  };
   140  
   141  export const getBlocksByCompactionLevel = (blocks: Block[], compactionLevel: number): Block[] => {
   142    if (compactionLevel === 0 || Number.isNaN(compactionLevel)) {
   143      return blocks;
   144    }
   145  
   146    const blockResult = blocks.filter((block) => block.compaction.level === compactionLevel);
   147    return blockResult;
   148  };
   149  
   150  export const getFilteredBlockPools = (
   151    blockPools: { [source: string]: BlocksPool },
   152    filteredBlocks: Block[]
   153  ): { [source: string]: BlocksPool } => {
   154    const newblockPools: { [source: string]: BlocksPool } = {};
   155    Object.keys(blockPools).map((key: string) => {
   156      const poolArrayIndex = blockPools[key];
   157      const poolArray = poolArrayIndex[Object.keys(poolArrayIndex)[0]];
   158      for (let i = 0; i < filteredBlocks.length; i++) {
   159        if (JSON.stringify(filteredBlocks[i].thanos.labels) === JSON.stringify(poolArray[0][0].thanos.labels)) {
   160          Object.assign(newblockPools, { [key]: blockPools[key] });
   161          break;
   162        }
   163      }
   164    });
   165    return newblockPools;
   166  };