中后台 dashboard 构建指南

Dashboard 是什么?

Dashboard 的中文直译是"仪表盘",这很容易就让人联想到汽车的仪表盘,一种反映车辆各系统工作状况的装置,有车速里程表、转速表、燃油表等。同时,还会有各式各样的指示灯或警报灯,例如冷却液液面警报灯、燃油量指示灯、充电指示灯等。司机可以很方便地从汽车仪表盘中获得汽车整体状况。

而 dashboard 沿袭了汽车仪表盘理念,在一个屏幕上有预设性地显示对用户关键的信息,并实时告知用户正在发生的情况。同时,Dashboard 进一步结合计算机互动的功能显示和传输信息,突破了报表要考虑纸面打印输出的限制。在 dashboard 页面中,用户不仅可以直接对数据和图表进行分析,还可以通过控件来控制数据的显示、计算、过滤和分组等等。

在 Stephen Few 的《Information Dashboard Design》一书中指出:Dashboard 对重要信息做视觉呈现,这些重要信息是为了达成一个或者多个目标而被统一组织在一屏内,以便能被够用户一眼囊括。即 dashboard 集中呈现重要信息,便于用户快速浏览获知全局。

基于 dashboard 这样的特性,在中后台应用中,dashboard 页面常常会被当做应用主页,成为专业用户们最常用的功能页面,如常见的系统监控大盘、后台数据大盘、成本分析大盘等,这些 dashboard 能够帮助用户高效的获取海量数据中的重要信息、快速发现异常、做出数据驱动型的决策。

如何构建 dashboard?

那么如何构建出一个好用的 dashboard 呢?

  1. 明确目标: 在构建一个 dashboard 之前,请先问问自己:这个 dashboard 的目标是什么?如果 dashboard 没有一个明确的目标,那么请问自己是否真的需要这个 dashboard。而这里的目标通常是期望 dashboard 能够回答的问题,例如:产品的增长趋势是什么样?服务集群、节点的运行状况如何?
  2. 数据获取与处理: 选择与目标相关的数据源,确保能够从中提炼出期望 dashboard 回答的问题的答案,避免数据的冗余。其次,在 dashboard 使用这些数据时,始终确保数据干净和正确,谁也不希望在使用 dashboard 几个月后才意识到数据一直都是错误的。
  3. 选择合适的图表: 数据可视化方式的多样性,让选择正确的图表类型变得尤为重要,但其核心思路非常明确:让图表专注于回答你提出的问题,例如,如果你的问题是"哪些服务器出现了问题?",那么也许您不需要显示所有服务器的数据,只需显示出问题的服务器的数据即可。同时数据与图表的组合要利于理解,避免不必要的认知负荷。
  4. 合理布局与简洁: Dashboard 通常都包含多个图表,图表之间的排列组合,需要划清主次,确保关键信息被突出展示,合理规划用户的浏览动线。单个 dashboard 内做到样式统一,以避免 dashboard 变得看起来杂乱无章,分散用户注意力。
  5. 持续迭代和改进: Dashboard 应该随着业务或需求的变化,持续迭代改进。

如何选择合适的图表?

下文会通过监控场景下图表使用的三个反模式,并结合相应的解决方案,来阐述如何选择正确的图表类型来解释你的数据。

💣 反模式1:数据千层饼(Phyllo graphs)

在监控场景下,监控目标通常都不是单一的,他们可能是一组服务器、容器或设备,当在监控多个执行相同工作的个体时,最理想的状态是,既能够快速查看到整体聚合的表现,也能够关注到每个个体的情况。乍一看,像上面这种堆叠面积图似乎非常适合这种"既要还要"的情况:总堆叠显示聚合数据,每个子面积又反应出对应个体的表现。

问题: 数据特征丢失,意义不明

堆叠面积图非常适合规模相对较小的群体,但随着群体规模的增加,并向图表中添加更多的面积块时,它的可视化效果将逐渐降低。大量的面积块积压在有限的高度内,自然会失去垂直方向的分辨率,难以感知数据的起伏变化,图表变成了一张数据千层饼。这样的图表也会拖累监控页面的性能:每次刷新时,需要下载和渲染大量不可见的信息。

解决方案:不要吝啬你的图表,分而治之

图表需要尽可能快地让人读懂。因此,图表信息过载的解决方案要么是减少图表中的信息,要么是将那些信息分散在多个图表中。

首先,可以为聚合值单独构建一张图表,显然这种单数据系列的时序图更清晰、更易读

此外,为了突出个体表现,可以配合下述的一些图表形成组合,来补充聚合图表:

  • 热力图 使用热力图来展示监控目标组的整体趋势,也可以发现离群值。

  • 折线图 使用折线图展示监控目标组的平均值、最大值和最小值随时间的变化情况。

这种分而治之的思想,将信息负载过重的"千层饼图"分成多个可视化部分,能够让用户更加快速、清晰地了解监控对象中发生的情况。即使最终图表数量变多了,但这样经过梳理的看板视图通常能在浏览器中获得更快的响应速度。

💣 反模式2:一刀切(Using one tool for everything)

时序折线图通用性极高,通常都是可视化图表选择的默认选项。由于它的坐标轴分别代表时间与数据值,非常易于理解,几乎在任何图表环境中都是合理的。但是,数据可视化没有银弹,极高的泛用性不意味着它是所有场景下的正确选择。

问题:面条化(Spaghettification)

在数据可视化中,"面条化"通常是指一个图形界面上有过多重叠的线或数据系列,使其看上去像一堆交错的意大利面条。就像上文堆叠面积图一样,过多的数据系列会导致图表信息表达的效率降低,成百上千根线条的重叠交织在一起,可谓是"剪不断,理还乱"。

解决方案:使用热力图

热力图是专门用于清晰呈现重叠数据序列的------它的主要特点之一是使用颜色的渐变来表示在特定范围内报告指标的个体数量。热力图对于监控大量主机、容器或其他监控目标时非常有用。它能够展现总体趋势,同时发现离群值和异常情况。

问题:线条跳动

在使用折线图去渲染那些随时间变化的指标时,最好先思考一下指标数据是如何随时间变化的。对于稀疏指标来说,折线图并不是一个好的选择,因为图表会尝试在不平滑的点之间进行插值,其结果是渲染出抖动、尖锐、反复变化的图形。

解决方案:使用柱状图

柱状图非常适合稀疏指标,图表中的每根条柱都是离散的元素,不会进行数据点之间的差值,因此指标数据的突然跃升不会导致两个不相干的数据点被连接起来,从而产生具有误导性的"趋势"线。

💣 反模式3:非必要求和(Summing something that shouldn't be summed)

堆叠面积图有时被用作解决图表面条化的方法,当我们从折线图切换到堆叠面积图时,能够有效地偏移每个数据序列的 y 轴,以防止重叠,让每个数据系列清晰展现,但...这真的是个好办法么?

问题:2 ms + 2 ms ≠ 4 ms

堆叠面积图默认会对数据系列求和,但许多指标根本不适合展示总和。例如,时延、CPU 使用率等指标就不应该在群组中求和(多个服务的时延累加起来并不代表整个系统的时延)。

解决方案:

  • 精度最重要时使用线图 对于诸如时延这样的度量指标,通常有明确的可接受阈值,此时折线图可以清晰的体现出阈值线。而当数据序列数量庞大时,保持折线图可读性的关键就在于数据的聚合和过滤,例如:可以仅绘制所有 host 时延数据的平均值和 P95 值,体现最近的性能情况。或者可以绘制每个数据中心的延迟,又或是仅绘制最慢的 10 个主机的延迟,以减少呈现的数据序列数量。

  • 趋势最重要时使用热力图 对于像 CPU 和系统负载这样的度量标准,您可能没有硬性的阈值,但您想知道何时利用率持续高或低。在这种情况下,热力图非常适合,因为它们清楚地显示了整个群体的趋势,并展示了离群值,即使是非常大的主机聚合体。

前端实践

当前业内已经有了相当多的 dashboard 解决方案,如 Grafana、Datadog 等产品都能帮助我们搭建出完善的 dashboard,但也不乏有些场景,需要业务自行开发 dashboard,尤其是在中后台应用中,会有一些更轻量、更定制化的 dashboard 使用场景,而这也对前端可视化技术提出了挑战。

图表库选择

目前前端可视化库可选择的种类繁多,而针对 dashboard 场景,最重要的考量因素无非是「图表能力」和「图表性能」两方面。对于图表能力,需要图表库能够支持丰富的图表类型,以应对不同类型数据的展示,同时需要支持较高的可交互性,如多图表之间的联动,数据的上卷下钻等等。而对于图表性能,在 dashboard 场景下,需要关注多实例情况下的表现。以下是对一些常见的图表库进行对比调研后得出的结论,仅供参考

性能排行
第一梯队 Chart.js
第二梯队 ECharts 、 HighCharts
第三梯队 BizCharts、AntDesignChart

:由于图表性能对比维度众多,如静态&动态数据、数据规模、不同图表类型、单&多实例等,很难比较出绝对的性能排名,因此结合多份 Benchmark 报告得出大致的性能梯队。

综合对比
维度 / 图表库 BizChart AntDesignChart ECharts Chart.js HighCharts
社区活跃度 ⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
文档可读性 ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐
图表能力 ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐
图表性能 ⭐⭐ ⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐

布局方案

React-Grid-Layout 是一个用于构建可拖拽和可调整大小的网格布局的 React 组件库。它提供了一个灵活的网格系统,可以帮助您创建自定义的 dashboard、布局编辑器和其他交互式网格布局。

React-Grid-Layout 具有以下主要特点:

  1. 可拖拽和可调整大小:您可以通过拖拽和调整大小的方式轻松地重新排列和调整网格中的组件。

  2. 响应式布局:React-Grid-Layout 支持响应式布局,可以根据不同的屏幕尺寸和设备自动调整网格布局。

  3. 自定义配置:您可以通过配置项来定义网格的行数、列数、间距、大小限制等,以满足您的具体需求。

  4. 事件处理:React-Grid-Layout 提供了丰富的事件处理功能,可以监听组件的拖拽、调整大小等操作,并触发相应的回调函数。

  5. 扩展性:React-Grid-Layout 可以与其他 React 组件和库无缝集成,使您能够根据需要扩展和定制网格布局。

性能调优

回顾前文,其实性能优化的首要任务是选择正确的图表类型,避免把过多不必要的数据塞进某个不合适图表中。在图表类型无法改变,并且已经选择了性能最佳的图表组件的前提下,可以尝试从以下几个方面进行性能调优。

数据 降采样

数据降采样是图表优化中的一种常用的策略,用于在大型数据集上减少数据点的数量,以提高图表的性能和可视化效果。降采样可以在保持可视化的整体趋势和信息完整性的同时,减少数据点的数量,从而减少图表渲染和数据传输的成本。需要注意的是,数据降采样可能会损失一部分细节信息,因此需权衡降低数据点数量和保留数据完整性之间的平衡。

目前许多图表库都支持开启了降采样策略,例如 ECharts 在折线图上提供 sampling 属性,用于配置当数据量远大于像素点时候的降采样策略,该属性默认关闭,当渲染性能出现问题时可以尝试开启,推荐使用 "lttb"

举个例子:当一个宽度为 300px 的时序折线图,每个 px 只能渲染一个数据点时,那么渲染超过 300 个点的数据是无意义的,用户并看不到那些重叠的数据点,此时便可以采用降采样策略将数据点约束到 300 个,并保持原先的视觉特性。

部分展示,图表分页

数据降采样只能解决折线图中单 series 数据量过多的问题。当 series 数量成为性能瓶颈时,可以调整数据展示策略,每次展示部分数据,减轻渲染压力。具体实现,可以考虑增加 legend 分页逻辑,确保图表每次渲染的 series 数量在性能可承受范围内;亦或是利用类似 ECharts 异步加载数据、动态更新的特性,渐进加载数据。总之,核心目标还是减少实际渲染的数据点数。

数据 懒加载

Dashboard 的每个 panel 通常都会有独立的数据请求逻辑,当全局筛选项、时间范围发生变化或者用户主动刷新时,便会触发 panel 内部的 fetch 。当一个 dashboard 包含大量 panel 时,用户也只能观察到视口范围内的为数不多 panel,而那些不可见 panel 的 fetch 便是无意义的。因此,很容易想到利用懒加载方式,规避掉不必要的请求,但需要注意的是,如果直接使用虚拟滚动这样的组件懒加载方式,那么对于已经渲染完成的图表,也会频繁的经历销毁和创建的过程,考虑到 dashboard 并不太可能会出现海量 panel 的场景,仅对 panel 数据进行懒请求即可。

简单来讲,只需要在 panel 在被触发onRefresh 时,判断当前 panel 是否处于视口范围内,如果不在:便将 refreshWhenInView置为true,然后忽略此次 onRefresh。同时监听 isInView的变化,当 panel 出现在视口内时,自动触发 onRefresh,并在 onRefresh 完成后,将refreshWhenInView置为false。这种不单一依赖isInView的方式,能够进一步避免不必要的请求。

scss 复制代码
  const [refreshWhenInView, setRefreshWhenInView] = useState(false);

  useEffect(() => {
    if (isInView && refreshWhenInView) {
      onRefresh();
    }
  }, [isInView]);

  const onRefresh = () => {
    if (!isInView) {
      setRefreshWhenInView(true);
      return;
    }
    setRefreshWhenInView(false);
    //... fetch data ...
  };

注: 如果使用 @react-grid-layout ,需要手动关闭 useCSSTransforms ,该功能默认开启,在首次渲染布局时,所有布局子元素会从布局容器左上角为起点,播放位移动画,会导致元素可见状态不准确。

写在最后

冷知识时间到!!!讲了这么多 dashboard,最后让我们回到 dashboard 一词本身,该词最早出现在 1846 年,指马车前部的木板或皮围裙,用于防止马蹄溅起的泥浆飞溅到车内,当汽车发明时,驾驶员前方保留了这块面板,并随着机械复杂性的提升,这块面板开始承载越来越多的功能,如挂载机械仪表, dashboard 一词作为仪表盘开始广泛运用到机械相关的领域,然后随着计算机技术和互联网的发展,dashboard 又逐渐引申到了数据可视化领域,变成了我们今天聊的 dashboard。

参考资料:

www.datadoghq.com/blog/anti-p...

cloud.tencent.com/developer/a...

echarts.apache.org/handbook/zh...

github.com/react-grid-...

相关推荐
Larcher29 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐42 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭1 小时前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu2 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端
六月的可乐2 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程