1import React, { FC } from 'react'; 2import { ScrapePool, getColor } from './target'; 3import { Collapse, Table, Badge } from 'reactstrap'; 4import styles from './ScrapePoolPanel.module.css'; 5import { Target } from './target'; 6import EndpointLink from './EndpointLink'; 7import TargetLabels from './TargetLabels'; 8import { now } from 'moment'; 9import { useLocalStorage } from '../../hooks/useLocalStorage'; 10import { ToggleMoreLess } from '../../components/ToggleMoreLess'; 11import { formatRelative, humanizeDuration } from '../../utils'; 12 13interface PanelProps { 14 scrapePool: string; 15 targetGroup: ScrapePool; 16} 17 18export const columns = ['Endpoint', 'State', 'Labels', 'Last Scrape', 'Scrape Duration', 'Error']; 19 20const ScrapePoolPanel: FC<PanelProps> = ({ scrapePool, targetGroup }) => { 21 const [{ expanded }, setOptions] = useLocalStorage(`targets-${scrapePool}-expanded`, { expanded: true }); 22 const modifier = targetGroup.upCount < targetGroup.targets.length ? 'danger' : 'normal'; 23 const id = `pool-${scrapePool}`; 24 const anchorProps = { 25 href: `#${id}`, 26 id, 27 }; 28 29 return ( 30 <div className={styles.container}> 31 <ToggleMoreLess event={(): void => setOptions({ expanded: !expanded })} showMore={expanded}> 32 <a className={styles[modifier]} {...anchorProps}> 33 {`${scrapePool} (${targetGroup.upCount}/${targetGroup.targets.length} up)`} 34 </a> 35 </ToggleMoreLess> 36 <Collapse isOpen={expanded}> 37 <Table className={styles.table} size="sm" bordered hover striped> 38 <thead> 39 <tr key="header"> 40 {columns.map((column) => ( 41 <th key={column}>{column}</th> 42 ))} 43 </tr> 44 </thead> 45 <tbody> 46 {targetGroup.targets.map((target: Target, idx: number) => { 47 const { 48 discoveredLabels, 49 labels, 50 scrapePool, 51 scrapeUrl, 52 globalUrl, 53 lastError, 54 lastScrape, 55 lastScrapeDuration, 56 health, 57 } = target; 58 const color = getColor(health); 59 60 return ( 61 <tr key={scrapeUrl}> 62 <td className={styles.endpoint}> 63 <EndpointLink endpoint={scrapeUrl} globalUrl={globalUrl} /> 64 </td> 65 <td className={styles.state}> 66 <Badge color={color}>{health.toUpperCase()}</Badge> 67 </td> 68 <td className={styles.labels}> 69 <TargetLabels discoveredLabels={discoveredLabels} labels={labels} scrapePool={scrapePool} idx={idx} /> 70 </td> 71 <td className={styles['last-scrape']}>{formatRelative(lastScrape, now())}</td> 72 <td className={styles['scrape-duration']}>{humanizeDuration(lastScrapeDuration * 1000)}</td> 73 <td className={styles.errors}>{lastError ? <Badge color={color}>{lastError}</Badge> : null}</td> 74 </tr> 75 ); 76 })} 77 </tbody> 78 </Table> 79 </Collapse> 80 </div> 81 ); 82}; 83 84export default ScrapePoolPanel; 85