The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/features/trails/banners/NativeHistogramBanner.tsx

287 lines
9.7 KiB

import { css } from '@emotion/css';
import { useState, type Dispatch, type SetStateAction } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, useTheme2, Alert, Button } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { DataTrail } from '../DataTrail';
import { reportExploreMetrics } from '../interactions';
import { MetricSelectedEvent } from '../shared';
interface NativeHistogramInfoProps {
histogramsLoaded: boolean;
nativeHistograms: string[];
trail: DataTrail;
}
export function NativeHistogramBanner(props: NativeHistogramInfoProps) {
const { histogramsLoaded, nativeHistograms, trail } = props;
const [histogramMessage, setHistogramMessage] = useState(true);
const [showHistogramExamples, setShowHistogramExamples] = useState(false);
const styles = useStyles2(getStyles, 0);
if (bannerHasBeenShown() || !histogramsLoaded || nativeHistograms.length === 0 || !histogramMessage) {
return null;
}
return (
<>
{
<Alert
title={t('trails.native-histogram-banner.title-native-histogram-support', 'Native histogram support')}
severity={'info'}
onRemove={() => {
// when a user explicitly closes the banner, save that it has been closed in local storage to not show again
setBannerHasBeenShown();
setHistogramMessage(false);
}}
className={styles.banner}
>
<div className={styles.histogramRow}>
<div className={styles.histogramSentence}>
<Trans i18nKey="trails.native-histogram-banner.sentence">
Prometheus native histograms offer high resolution, high precision, simple usage in instrumentation and
a way to combine and manipulate histograms in queries and in Grafana.
</Trans>
</div>
<div className={styles.histogramLearnMore}>
<div>
<Button
onClick={() =>
window.open('https://grafana.com/docs/grafana-cloud/whats-new/native-histograms/', '_blank')
}
className={styles.button}
>
<Trans i18nKey="trails.native-histogram-banner.learn-more">Learn more</Trans>
</Button>
</div>
</div>
</div>
<NativeHistogramExamplesButton
showHistogramExamples={showHistogramExamples}
setShowHistogramExamples={setShowHistogramExamples}
/>
{showHistogramExamples && (
<NativeHistogramExamples
trail={trail}
nativeHistograms={nativeHistograms}
setHistogramMessage={setHistogramMessage}
/>
)}
</Alert>
}
</>
);
}
interface NativeHistogramExamplesButtonProps {
showHistogramExamples: boolean;
setShowHistogramExamples: Dispatch<SetStateAction<boolean>>;
}
const NativeHistogramExamplesButton = ({
showHistogramExamples,
setShowHistogramExamples,
}: NativeHistogramExamplesButtonProps) => {
const styles = useStyles2(getStyles, 0);
return (
<div>
<Button
className={`${styles.seeExamplesButton} native-histogram-examples-button`}
type="button"
fill="text"
variant="primary"
onClick={() => {
if (showHistogramExamples) {
// hide the examples
reportExploreMetrics('native_histogram_examples_closed', {});
}
setShowHistogramExamples(!showHistogramExamples);
}}
>
{showHistogramExamples
? t(`trails.native-histogram-banner.hide-examples`, `Hide examples`)
: t(`trails.native-histogram-banner.see-examples`, `> See examples`)}
</Button>
</div>
);
};
type NativeHistogramExamplesProps = Pick<NativeHistogramInfoProps, 'trail' | 'nativeHistograms'> & {
setHistogramMessage: Dispatch<SetStateAction<boolean>>;
};
const NativeHistogramExamples = ({ trail, nativeHistograms, setHistogramMessage }: NativeHistogramExamplesProps) => {
const styles = useStyles2(getStyles, 0);
const isDark = useTheme2().isDark;
const selectNativeHistogram = (metric: string) => {
reportExploreMetrics('native_histogram_example_clicked', {
metric,
});
trail.publishEvent(new MetricSelectedEvent(metric), true);
};
const images = {
nativeHeatmap: isDark
? 'public/img/native-histograms/DarkModeHeatmapNativeHistogram.png'
: 'public/img/native-histograms/LightModeHeatmapNativeHistogram.png',
classicHeatmap: isDark
? 'public/img/native-histograms/DarkModeHeatmapClassicHistogram.png'
: 'public/img/native-histograms/LightModeHeatmapClassicHistogram.png',
nativeHistogram: isDark
? 'public/img/native-histograms/DarkModeHistogramNativehistogram.png'
: 'public/img/native-histograms/LightModeHistogramClassicHistogram.png',
classicHistogram: isDark
? 'public/img/native-histograms/DarkModeHistogramClassicHistogram.png'
: 'public/img/native-histograms/LightModeHistogramClassicHistogram.png',
};
return (
<>
<div className={`${styles.histogramRow} ${styles.seeExamplesRow}`}>
<div className={styles.histogramImageCol}>
<div>
<Trans i18nKey="trails.native-histogram-banner.now">Now:</Trans>
</div>
</div>
<div className={`${styles.histogramImageCol} ${styles.rightCol}`}>
<div>
<Trans i18nKey="trails.native-histogram-banner.previously">Previously:</Trans>
</div>
</div>
</div>
<div className={`${styles.histogramRow} ${styles.seeExamplesRow}`}>
<div className={styles.histogramImageCol}>
<div className={styles.histogramRow}>
<div className={`${styles.histogramImageCol} ${styles.fontSmall}`}>
<div className={styles.imageText}>
<Trans i18nKey="trails.native-histogram-banner.nh-heatmap">
Native Histogram displayed as heatmap:
</Trans>
</div>
<div>
<img width="100%" src={images.nativeHeatmap} alt="Native Histogram displayed as heatmap" />
</div>
</div>
<div className={`${styles.histogramImageCol} ${styles.fontSmall}`}>
<div className={styles.imageText}>
<Trans i18nKey="trails.native-histogram-banner.nh-histogram">
Native Histogram displayed as histogram:
</Trans>
</div>
<div>
<img width="100%" src={images.nativeHistogram} alt="Native Histogram displayed as histogram" />
</div>
</div>
</div>
</div>
<div className={`${styles.histogramImageCol} ${styles.rightImageCol} ${styles.rightCol}`}>
<div className={styles.histogramRow}>
<div className={`${styles.histogramImageCol} ${styles.fontSmall}`}>
<div className={styles.imageText}>
<Trans i18nKey="trails.native-histogram-banner.ch-heatmap">
Classic Histogram displayed as heatmap:
</Trans>
</div>
<div>
<img width="100%" src={images.classicHeatmap} alt="Classic Histogram displayed as heatmap" />
</div>
</div>
<div className={`${styles.histogramImageCol} ${styles.fontSmall}`}>
<div className={styles.imageText}>
<Trans i18nKey="trails.native-histogram-banner.ch-histogram">
Classic Histogram displayed as histogram:
</Trans>
</div>
<div>
<img width="100%" src={images.classicHistogram} alt="Classic Histogram displayed as histogram" />
</div>
</div>
</div>
</div>
</div>
<br />
<div>
<Trans i18nKey="trails.native-histogram-banner.click-histogram">
Click any of the native histograms below to explore them:
</Trans>
</div>
<div>
{nativeHistograms.map((el) => {
return (
<div key={el}>
<Button
onClick={() => {
selectNativeHistogram(el);
setHistogramMessage(false);
}}
key={el}
variant="primary"
size="sm"
fill="text"
className={`native-histogram-example-clicked`}
>
{t('trails.native-histogram-banner.metric-examples', el)}
</Button>
</div>
);
})}
</div>
</>
);
};
function getStyles(theme: GrafanaTheme2, _chromeHeaderHeight: number) {
return {
banner: css({
flexGrow: 0,
}),
histogramRow: css({
display: 'flex',
flexDirection: 'row',
gap: theme.spacing(2),
}),
histogramSentence: css({
width: '90%',
}),
histogramLearnMore: css({
width: '10%',
}),
button: css({
float: 'right',
}),
seeExamplesButton: css({
paddingLeft: '0px',
}),
seeExamplesRow: css({
paddingTop: '4px',
}),
histogramImageCol: css({
display: 'flex',
flexDirection: 'column',
flexBasis: '100%',
flex: '1',
}),
fontSmall: css({
fontSize: theme.typography.size.sm,
}),
imageText: css({
paddingBottom: '4px',
}),
rightImageCol: css({
borderLeft: `1px solid ${theme.colors.secondary.borderTransparent}`,
}),
rightCol: css({
paddingLeft: '16px',
}),
};
}
export function setBannerHasBeenShown() {
localStorage.setItem('nativeHistogramBanner', 'true');
}
export function bannerHasBeenShown() {
return localStorage.getItem('nativeHistogramBanner') ?? false;
}