在我们生活的数字时代,数据无处不在。它来自 Web 和移动应用、物联网设备、社交媒体互动和 CRM 系统等。作为一个 SaaS 创业者,我深知,当涉及用户行为分析和可视化时,这些大量的数据源可能会让人难以招架。这里的挑战不仅仅在于如何收集数据,还在于管理和分析数据,从数据中获取洞察。
经过一段时间的探索,我找到了一个有效的解决方案,那就是建立一个集中的数据处理 pipeline,包括从不同来源收集用户数据,将其存储在一个数据库中,然后对这些数据进行实时分析和可视化,得到关于产品和用户使用的洞察。这就像拥有一个满足所有数据需求的一站式数据中心,对于决策过程非常有用。
如果你一直关注我的系列文章,你会知道我在持续探索 OceanBase,并将其整合到各种项目中。但我选择 OceanBase 不仅仅是因为对它的熟悉程度。在实时分析和大数据量处理方面,OceanBase 确实令人印象深刻。它不仅可以处理大量数据,而且是在没有任何性能影响的情况下,高效处理这些数据。
在接下来的几节中,我将带你了解我如何使用 OceanBase、Jitsu 和 Metabase 来构建用一个用户事件数据分析 pipeline。这个过程很有趣,也希望以此来激发大家不断探索这些工具和它们提供的各种可能性。
本项目使用的工具
在这个项目中,我使用了三个关键工具:OceanBase、Jitsu 和 Metabase。每个工具在用户分析 pipeline 的数据收集、存储和分析中扮演着关键角色。
OceanBase 作为存储用户事件的核心数据库,是这个项目的核心。它是一款开源的分布式 SQL 数据库,具备扩展性和高效处理大量数据的能力,是该项目中数据库的理想选择。
Jitsu 是一款开源的数据收集平台,用于捕获 Web 和移动应用等各个平台上的用户事件。它收集数据并直接发送到 OceanBase。
Metabase 是一款开源的商业智能工具,用于可视化和分析存储在 OceanBase 中的数据。它提供了一个用户友好的界面,用于探索数据和生成洞察。这些工具共同创建了一个全面的实时用户行为分析 pipeline。
以下是项目的示意图:
针对这个项目,我使用了 Gitpod 来简化开发环境的设置,其中包括 OceanBase、Jitsu、Metabase 和一个 SvelteKit 演示 APP。演示 APP 模拟了一个真实的 Web 应用程序,允许我生成用户交互并将数据发送到 pipeline 中,并展示系统如何处理实时数据。
整个项目的代码库都可以在 GitHub 上获取,任何有兴趣的人都可以参与进来。你可以直接在 Gitpod 中打开这个项目,并自己尝试上手搭建项目。这种实践方法可以让你更直观地了解每个组件在 pipeline 中的交互方式,并有机会在真实环境中探索这些工具。
设置 GitPod 环境
如前所述,我们将使用 GitPod 来设置项目的开发环境。对于不熟悉 GitPod 的人来说,GitPod 允许你使用一个 .gitpod.yml 文件来定义开发环境的配置。这个文件是用 YAML 编写的,位于项目仓库的根目录中。它详细说明了 GitPod 准备开发环境所需的一切。
我们的 .gitpod.yml 文件包括了 OceanBase、Jitsu、Metabase 和连接这些服务的网络的设置。让我们来详细介绍一下每个服务的设置:
1、初始化镜像
在我们可以使用 pipeline 中的服务之前,我们首先需要为 GitPod 环境设置一个镜像。
image:file:.gitpod.Dockerfile
.gitpod.Dockerfile 是 Gitpod 为工作区构建自定义 Docker 镜像的配置文件。它安装 Docker 引擎、Docker CLI 和 containerd 服务。
FROM gitpod/workspace-fullUSER gitpodRUN sudo apt-get update && sudo apt-get install -y \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-common# Install DockerRUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -RUN sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"RUN sudo apt-get updateRUN sudo apt-get install -y docker-ce docker-ce-cli containerd.io# Allow the gitpod user to execute docker commandsRUN sudo usermod -aG docker gitpod
2、Metabase设置
在 .gitpod.yml 文件的 tasks 部分中,我们使用 Docker 设置了 Metabase。我们指示 Docker 运行一个 Metabase 实例,将其绑定到端口 4000,并将其附加到我们自定义的网络 pipeline_network。
tasks:- init: docker network create pipeline_network- init: echo 'Setting up Metabase...'command: docker run -d -p 4000:3000 --name metabase --network=pipeline_network metabase/metabase
3、Jitsu设置
接下来,我们在初始化阶段通过运行 jitsu-setup.sh的bash 脚本来设置 Jitsu。一旦设置脚本完成,Docker Compose 就会根据 jitsu-docker-compose.yml 中的规范指示启动 Jitsu 服务。
- init: bash jitsu-setup.shcommand: docker compose -f jitsu-docker-compose.yml up
4、OceanBase设置
对于 OceanBase,我们首先从 Docker Hub 拉取 OceanBase 镜像。一旦镜像在本地可用,我们就启动一个新的 OceanBase 容器,将其连接到我们的网络上,并暴露端口 2881。然后运行 bash 脚本 oceanbase-gitpod-init.sh 来完成设置。
- name: OceanBaseinit: docker pull oceanbase/oceanbase-cecommand: |echo "alias sh='/bin/bash'" >> ~/.profilesource ~/.profiledocker run --network=pipeline_network -p 2881:2881 --name obstandalone -e MINI_MODE=1 -d oceanbase/oceanbase-cebash oceanbase-gitpod-init.sh
5、端口配置
最后,我们定义了服务暴露的端口。Jitsu Web 服务器在端口 3216 上对外可见。然而,Metabase 服务器和 OceanBase 数据库分别在端口 4000 和 2881 上暴露,但只在个人网络可见。
ports:- name: Jitsu Serverdescription: The Jitsu web serverport: 3216visibility: public- name: Metabase Serverport: 4000visibility: private- name: OceanBase Databaseport: 2881visibility: private
这种配置使我们在打开 GitPod 项目时就能够拥有一个准备就绪的编码环境,从而省去了手动设置和配置的麻烦。
运行 GitPod 环境
一旦你的项目代码托管在 GitHub 上,并且你的 Gitpod 配置文件(/.gitpod.yml和/.gitpod.Dockerfile)在你的代码库的根目录中设置好,你就可以启动 Gitpod 环境了。
要在 GitPod 中打开该项目,可以使用 GitPod 识别的特殊 URL 格式。只需在 GitHub 仓库的 URL 前加上 https://gitpod.io/#。例如,如果你的 GitHub 仓库位于 https://github.com/username/repo,则可以通过在浏览器中导航到https://gitpod.io/#https://github.com/username/repo 来在 Gitpod 中打开它。
访问此 URL 后,Gitpod 将开始一个新的工作区并根据你的 .gitpod.yml 和 .gitpod.Dockerfile 文件进行准备。这包括设置 OceanBase、Jitsu 和 Metabase,并启动 SvelteKit 演示 APP。
一旦工作区准备就绪,将在浏览器中看到一个编码环境和正在运行中的终端。从这里开始,就可以像在本地机器上一样与项目进行交互。
一旦进入 Gitpod 工作区,你会注意到所有服务都已开始运行。你可以通过检查终端输出并观察正在运行的程序来确认这一点。
确认所有服务都在 Gitpod 工作区平稳运行,且已经准备好实时数据处理和可视化,就可以立即着手进行下一步。
一旦 Gitpod 环境启动并运行,下一步就是配置 Jitsu 和 Metabase,并与 OceanBase 连接。
1、Jitsu 设置
在 Jitsu 中,首先是添加一个新的数据目标。由于 OceanBase 与 MySQL 兼容,因此可以从列表中选择 MySQL 数据库类型。由于 Jitsu 和 OceanBase 在同一网络中运行,也可以使用 localhost 或 127.0.0.1 作为主机名。连接 OceanBase 的端口是 2881。
在 Jitsu 中,还可以添加一个发送数据的网站。记得保存前端和后端的写入密钥。
2、Metabase 设置
设置 Metabase 的过程类似。Metabase 在 GitPod 工作区中运行在端口 4000 上。需要将 OceanBase 作为数据源连接到 Metabase 中。和 Jitsu 一样,可以使用 localhost 或者 127.0.0.1 作为主机名连接到 OceanBase。
通过这种方式设置 Jitsu 和 Metabase,可以创建一个 pipeline,其中用户事件被 Jitsu 捕获,存储在 OceanBase 中,并在 Metabase 中进行可视化和分析。这个设置构成了我们实时用户分析 pipeline 的基础。
下一步是使用 Jitsu 的前端 SDK 来捕获事件。
在演示 APP 中捕获事件
用户分析 pipeline 中的下一个关键步骤是捕获用户事件。为此,我们将使用 Jitsu 的前端 SDK 与 SvelteKit 演示 APP 结合使用。
1、设置演示 APP
首先,我们将在项目的根目录中创建一个名为 app 的文件夹。这个文件夹将容纳我们的 SvelteKit 演示 APP。我们将使用以下命令克隆一个开源的 SvelteKit 应用 APP 到这个文件夹中:
git clone https://github.com/tsukhu/sveltekit-demo.git .一旦 APP 被克隆,我们需要安装它的依赖项。在终端中,进入 app 目录并运行 npm install 命令。此命令将为 SvelteKit APP 安装所有必要的软件包。
安装完所有的软件包后,启动开发服务器。在终端中运行 npm run dev 命令。此命令会启动 SvelteKit APP,你可以直接在 GitPod 工作区中访问它。
这个演示的 SvelteKit APP 包含了一个用户认证模块和几个演示功能,包括使用 Google 登录、待办事项 APP 和一个计数器 APP。它可以用来模拟一个真实应用程序中发生的情况:用户在应用程序中注册或登录,并使用 APP 的功能。
随着 SvelteKit 演示 APP 的运行,我们现在可以集成 Jitsu 的前端 SDK 集成,来捕获用户事件。这个设置使我们能够模仿现实世界的用户交互并测试我们的用户分析 pipeline。
2、在演示 APP 中使用 Jitsu SDK
Jitsu 的 SDK 可以通过 @jitsu/js NPM 包直接从 JavaScript 代码跟踪事件。它是同构的,意味着它可以在浏览器和 Node.js 环境中使用。
要安装 Jitsu SDK,需要在终端中运行以下命令:
npm install @jitsu/js这个命令将 @jitsu/js 包添加到项目中,使得 Jitsu 的分析函数可供使用。
现在我们可以返回到我们的 SvelteKit 代码中,添加事件跟踪代码。首先,在 /src/action 文件夹下,我们可以添加一个 jitsu.ts 文件,并使用以下代码:
import { jitsuAnalytics } from "@jitsu/js";export async function track(userEmail:string, event: string) {const analytics = jitsuAnalytics({host: "https://3216-wayneshn-oceanbasepipel-yr7spzlvu3y.ws-eu104.gitpod.io",// Browser Write Key configured on Jitsu Site entity.// If no Browser Write Key is added for Site entity, Site ID value can be used a Write Key.writeKey: "YOUR_JITSU_WRITE_KEY_FRONTEND",});await analytics.track(event, {userEmail: userEmail})}
这段代码主要导入了 Jitsu 库,并导出一个函数,该函数可以将用户邮箱和事件类型发送到我们刚刚设置的 Jitsu 服务器。
请记住将 “YOUR_JITSU_WRITE_KEY_FRONTEND” 替换为实际 Jitsu 前端写入密钥。
通过此设置,现在可以在整个 SvelteKit APP 中使用 track 函数将用户事件发送到 Jitsu 服务器。
2、使用 track 函数
一旦设置了 track 函数,就可以在整个 APP 中用它来捕获各种用户事件。例如,跟踪用户登录事件。
在 src/Auth.ts 文件中,可以按如下方式集成 track 函数:
import { env } from '$env/dynamic/public';import { browser } from '$app/environment';import { getApps, getApp, initializeApp } from '@firebase/app';import { getAuth, GoogleAuthProvider, signInWithPopup } from '@firebase/auth';import type { FirebaseOptions } from '@firebase/app';import type { Auth, UserCredential } from '@firebase/auth';import { track } from './actions/jitsu';const config: FirebaseOptions = {apiKey: env.PUBLIC_FIREBASE_API_KEY as string,authDomain: env.PUBLIC_FIREBASE_AUTH_DOMAIN as string,projectId: env.PUBLIC_FIREBASE_PROJECT_ID as string,storageBucket: env.PUBLIC_FIREBASE_STORAGE_BUCKET as string,messagingSenderId: env.PUBLIC_FIREBASE_MESSAGING_SENDER_ID as string,appId: env.PUBLIC_FIREBASE_APP_ID as string};if (browser && !getApps().length) {initializeApp(config);}export const getAppAuth = (): Auth => {return getAuth(getApp());};export const googleProvider = new GoogleAuthProvider();export const signIn = (): Promise<UserCredential | void> => {if (browser) {const auth = signInWithPopup(getAppAuth(), googleProvider);auth.then(data=> {track(data.user.email, "SignIn")})return auth} else {return new Promise((r) => r());}};
在这个代码片段中,有一个 signIn 函数,用于处理通过 Google 使用 Firebase 的用户登录。成功登录后,调用 track 函数,将用户的邮箱和事件类 "SignIn" 作为参数进行调用。这样就将登录事件发送到了 Jitsu 服务器进行追踪。
通过在代码中事件发生的位置调用 track 函数,并传入适当的参数,可跟踪任何用户事件。通过 APP 中集成这种追踪,可以捕获各种用户交互并获得有价值的用户行为洞察。
同样的方法可以应用到 APP 中的其他用户事件。例如,演示 APP 中有待办事项列功能,因此我们可以跟踪与其相关的事件。
在 Svelte 组件的脚本部分,位于 /src/components/Todo.svelte 文件中的待办事项列表功能中,可以插入 track 函数,如下所示:
import TodoList from './TodoList.svelte';import type { TodoType } from './TodoList.svelte';import { track } from '$src/actions/jitsu';import authStore from '$src/stores/authStore';let lastId = 0;const createTodo = (text: string, done = false): TodoType => ({ id: ++lastId, text, done });let todoText = '';let todos: TodoType[] = [createTodo('learn SvelteKit', true)];$: upcompletedCount = todos.filter((t) => !t.done).length;$: status = `${upcompletedCount} of ${todos.length} remaining`;function addTodo() {todos = todos.concat(createTodo(todoText));todoText = '';track($authStore.user?.email, 'AddTodo')}const archiveCompleted = () => {todos = todos.filter((t) => !t.done)track($authStore.user?.email, 'CompleteTodo')};const deleteTodo = (todoId: number) => {todos = todos.filter((t) => t.id !== todoId)track($authStore.user?.email, 'DeleteTodo')};function toggleDone(id: number) {todos = todos.map((t) => (t.id === id ? { ...t, done: !t.done } : t));}
这段代码首先导入了 tract 函数,然后当用户执行 addTodo 函数时,它会跟踪用户的邮箱,并向 Jitsu 发送一个 “AddTodo” 事件。
由于演示 APP 还具有计数器、贷款计算和天气查询等功能,我们可以在相应的功能中添加跟踪代码。
在Metabase中进行数据可视化
在设置了跟踪代码之后,APP 的用户交互被 Jitsu 捕获。所有这些事件都已被实时记录下来。
数据也同样存储在 OceanBase 数据库中。
为了使数据更有意义并模拟真实场景,我编写了一个脚本来模拟 APP 中的用户活动,基本上是自动化用户与 APP 的交互,例如登录、添加和完成任务以及删除任务。
结果生成了数千行数据。现在,我们的 OceanBase 数据库包含大约 6000 行数据。随着脚本的运行,新的模拟用户事件数据也不断涌现。
有了存储在 OceanBase 数据库中的用户事件数据以及连接到我们 OceanBase 实例的 Metabase,我们现在可以利用 Metabase 的功能来可视化和分析数据。
Metabase 提供了一个用户界面来创建各种类型的图表、表格和仪表板。你可以直接编写 SQL 查询从 OceanBase 数据库中获取数据,或者使用内置的查询生成器以实现更具可视性的方法。
例如,如果我们想了解过去 6 个月每周有多少新注册用户,我们可以使用以下 SQL 语句:
SELECTDATE_ADD(DATE(timestamp), INTERVAL(1-DAYOFWEEK(timestamp)) DAY) AS Week_Start,COUNT(DISTINCT user_email) AS New_UsersFROMeventsWHEREtimestamp >= DATE_SUB(NOW(), INTERVAL 6 MONTH)AND event = 'Register'GROUP BYWeek_StartORDER BYWeek_Start DESC;
这个语句对每个给定周内的“注册”事件进行计数,并返回每周新用户的表。我们还可以在 Metabase 中可视化该表:
月活用户数(MAU)是许多在线服务的关键业务指标。它表示一个月内与该服务交互的用户数。要计算每周 MAU 数据的变化,可以使用以下 SQL 语句:
SELECTDATE_ADD(DATE(timestamp), INTERVAL(1-DAYOFWEEK(timestamp)) DAY) AS Week_Start,COUNT(DISTINCT user_email) AS Weekly_Active_UsersFROMeventsWHEREtimestamp >= DATE_SUB(NOW(), INTERVAL 9 MONTH)AND event IN ('DeleteTodo', 'AddTodo', 'DeleteTodo', 'ReSetCounter', 'MinusCounter', 'CompleteTodo', 'SignIn', 'Register', 'Subscribe', 'ViewPricing')GROUP BYWeek_StartHAVINGCOUNT(DISTINCT user_email) >= 2ORDER BYWeek_Start DESC;
在这个查询中,timestamp 是事件发生的时间戳,user_email 是触发事件的用户的标识符,而 events 是存储事件数据的表。这个 SQL 语句根据事件发生的时间进行分组,计算每个星期的不同用户数量,并且只包括过去 9 个月的数据。
event IN ('DeleteTodo', 'AddTodo', 'DeleteTodo', 'ReSetCounter', 'MinusCounter', 'CompleteTodo', 'SignIn', 'Register', 'Subscribe', 'ViewPricing')条件确保只考虑指定类型的事件-只有当用户进行表中的事件时,他们才会被视为“活跃用户”。
同样,我们还可以编写 SQL 代码来可视化每天的用户增长和总事件数。
Metabase 的优点在于,它可以建立一个仪表板,将所有关键业务数据放在一个页面上,并每分钟刷新一次。
以下是使用 Metabase 建立的仪表板,提取了关于演示 APP 的所有关键信息,并将它们显示在一个页面上,数据每分钟更新一次。
结论
在本文中,我们介绍了如何使用 OceanBase 构建一个以 OceanBase 为中心的实时用户分析 pipeline 的过程。我们了解了 OceanBase 与 Jitsu 和 Metabase 结合使用,为不同来源的用户事件数据提供强大的处理、分析和可视化解决方案。
我们构建的 pipeline 从不同来源收集用户数据,将其存储在 OceanBase 中,然后对数据进行实时分析和可视化。这为产品和用户与产品的交互提供了宝贵的洞察。
此外,项目的整个代码库可在 GitHub 上获取。欢迎大家使用该项目,并在 Gitpod 中打开以自行尝试搭建 pipeline。请注意,运行 OceanBase 需要大量内存,因此建议使用具有 16GB 内存的大型 GitPod 实例。




