github.com/thanos-io/thanos@v0.32.5/pkg/ui/react-app/src/pages/alerts/CollapsibleAlertPanel.tsx (about)

     1  import React, { FC, useState, Fragment } from 'react';
     2  import { Alert, Collapse, Table, Badge } from 'reactstrap';
     3  import { RuleStatus } from './AlertContents';
     4  import { Rule } from '../../types/types';
     5  import { faChevronDown, faChevronRight } from '@fortawesome/free-solid-svg-icons';
     6  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
     7  import { createExternalExpressionLink, formatDuration } from '../../utils/index';
     8  
     9  interface CollapsibleAlertPanelProps {
    10    rule: Rule;
    11    showAnnotations: boolean;
    12  }
    13  
    14  const alertColors: RuleStatus<string> = {
    15    firing: 'danger',
    16    pending: 'warning',
    17    inactive: 'success',
    18  };
    19  
    20  const CollapsibleAlertPanel: FC<CollapsibleAlertPanelProps> = ({ rule, showAnnotations }) => {
    21    const [open, toggle] = useState(false);
    22  
    23    return (
    24      <>
    25        <Alert fade={false} onClick={() => toggle(!open)} color={alertColors[rule.state]} style={{ cursor: 'pointer' }}>
    26          <FontAwesomeIcon icon={open ? faChevronDown : faChevronRight} fixedWidth />
    27          <strong>{rule.name}</strong> ({`${rule.alerts.length} active`})
    28        </Alert>
    29        <Collapse isOpen={open} className="mb-2">
    30          <pre className="alert-cell">
    31            <code>
    32              <div>
    33                name: <a href={createExternalExpressionLink(`ALERTS{alertname="${rule.name}"}`)}>{rule.name}</a>
    34              </div>
    35              <div>
    36                expr: <a href={createExternalExpressionLink(rule.query)}>{rule.query}</a>
    37              </div>
    38              {rule.duration > 0 && (
    39                <div>
    40                  <div>for: {formatDuration(rule.duration * 1000)}</div>
    41                </div>
    42              )}
    43              {rule.labels && Object.keys(rule.labels).length > 0 && (
    44                <div>
    45                  <div>labels:</div>
    46                  {Object.entries(rule.labels).map(([key, value]) => (
    47                    <div className="ml-4" key={key}>
    48                      {key}: {value}
    49                    </div>
    50                  ))}
    51                </div>
    52              )}
    53              {rule.annotations && Object.keys(rule.annotations).length > 0 && (
    54                <div>
    55                  <div>annotations:</div>
    56                  {Object.entries(rule.annotations).map(([key, value]) => (
    57                    <div className="ml-4" key={key}>
    58                      {key}: {value}
    59                    </div>
    60                  ))}
    61                </div>
    62              )}
    63            </code>
    64          </pre>
    65          {rule.alerts.length > 0 && (
    66            <Table bordered size="sm">
    67              <thead>
    68                <tr>
    69                  <th>Labels</th>
    70                  <th>State</th>
    71                  <th>Active Since</th>
    72                  <th>Value</th>
    73                </tr>
    74              </thead>
    75              <tbody>
    76                {rule.alerts.map((alert, i) => {
    77                  return (
    78                    <Fragment key={i}>
    79                      <tr>
    80                        <td style={{ verticalAlign: 'middle' }}>
    81                          {Object.entries(alert.labels).map(([k, v], j) => {
    82                            return (
    83                              <Badge key={j} color="primary" className="mr-1">
    84                                {k}={v}
    85                              </Badge>
    86                            );
    87                          })}
    88                        </td>
    89                        <td>
    90                          <h5 className="m-0">
    91                            <Badge color={alertColors[alert.state] + ' text-uppercase'} className="px-3">
    92                              {alert.state}
    93                            </Badge>
    94                          </h5>
    95                        </td>
    96                        <td>{alert.activeAt}</td>
    97                        <td>{alert.value}</td>
    98                      </tr>
    99                      {showAnnotations && <Annotations annotations={alert.annotations} />}
   100                    </Fragment>
   101                  );
   102                })}
   103              </tbody>
   104            </Table>
   105          )}
   106        </Collapse>
   107      </>
   108    );
   109  };
   110  
   111  interface AnnotationsProps {
   112    annotations: Record<string, string>;
   113  }
   114  
   115  export const Annotations: FC<AnnotationsProps> = ({ annotations }) => {
   116    return (
   117      <Fragment>
   118        <tr>
   119          <td colSpan={4}>
   120            <h5 className="font-weight-bold">Annotations</h5>
   121          </td>
   122        </tr>
   123        <tr>
   124          <td colSpan={4}>
   125            {Object.entries(annotations).map(([k, v], i) => {
   126              return (
   127                <div key={i}>
   128                  <strong>{k}</strong>
   129                  <div>{v}</div>
   130                </div>
   131              );
   132            })}
   133          </td>
   134        </tr>
   135      </Fragment>
   136    );
   137  };
   138  
   139  export default CollapsibleAlertPanel;