操作日志 API:客户如何在自己的工作流中使用个人资料事件


Alex Phillips
Customer Service Specialist
标准的 Octo Browser 界面向您展示您的配置文件目前正在发生什么。但是,当一个团队管理数百或数千个配置文件时,他们有时需要自动将配置文件事件发送到 CRM、访问控制系统或内部仪表板。
这就是 Octo 的操作日志的作用:一个实时发送事件的 WebSocket 端点。我们为那些已将 Octo 集成到自己的 CRM、ERP 或财务系统中的团队添加了此功能。目前,Octo 操作日志支持十种事件类型——从配置文件的启动和停止到转移、删除和代理更改——随着团队发现新的使用场景,该列表还在不断增加。
在下方,您可以找到在实践中如何使用操作日志的两个示例:实时访问控制和大规模管理账号。
内容
管理任意数量的账户,无需担心被封禁、重复操作和不必要的开支。
想以优惠价体验 Octo Browser 吗?
使用促销码 OCTOBLOG 即可享受任意订阅 7 折优惠。此优惠仅对新用户有效。
无需手动验证的访问权限
我们的一位客户让来自不同部门的员工使用 Octo Browser 配置文件。每位员工都通过与 Octo 配合使用的自定义扩展拥有自己的访问级别。在授予所需权限之前,系统需要知道当前是谁在操作特定的配置文件。
在没有操作日志的情况下,无法准确查看是谁启动了配置文件。访问级别系统只能依赖间接指标:它可以检测到配置文件正在被使用,但无法得知是谁在使用它。
当我们在操作日志中添加了 profiles.started: user_email 事件后,流程发生了变化,从而可以自动应用权限。这种“事件 → 权限”的关联成为了我们大多数客户内部自动化的基石。
这是一个持续运行的机制,对每次配置文件的启动进行实时响应。事件会即时处理并存储在客户自己的数据库中。
我们的客户只需要一名开发人员和大约一个小时的时间就能集成操作日志。操作日志是作为附加模块添加到他们现有的权限系统中的,而不需要从头开始重构流程。
团队账目统计:数秒搞定,无需数小时
另一位客户使用分布式团队处理大量账号:许多人和许多配置文件同时进行处理。在这种规模下,很容易失去对全局的掌控:每个人正在处理多少个配置文件、有多少个已准备就绪、分配了多少个、删除了多少个,以及由谁删除和原因为何。
在切换到自己的系统之前,该团队在电子表格中记录所有内容。任何团队现状的快照都需要手动查看标签和记录。收集最新数据需要花费几个小时到一整天的时间,而当报告准备好时,部分信息已经过时了。
在我们扩展了操作日志之后,客户构建了他们自己的 CRM,该系统通过 API 接收配置文件事件,并将它们整合到一个统一的视图中:每位员工正在处理多少个配置文件、有多少个已准备就绪、分配了多少个以及删除了多少个,每项操作都与执行该操作的人员和时间相关联。
所有数据都以计数器和状态的形式显示在仪表板上并自动更新。以前需要花费数小时准备的报告,现在只需 30 秒即可生成——您只需打开相关板块即可。
该系统是在没有内部开发人员的情况下,使用 AI 编程工具开发的。仅用了一周时间就创建了集成 API 的 CRM 实用版本。
操作日志的其他用途
Octo 的 API 可以处理不同的任务:实时运行控制、活动跟踪和内部流程自动化。在上述两种情况下,集成只需数小时或数天,而不是数月,并且不需要专门的开发团队。
在每个场景中,其原理都是相同的:Octo 实时发送配置文件活动事件,而客户的系统决定如何处理和存储这些事件以及将它们用于何处。
真正的客户需求在操作日志的开发中起着至关重要的作用。应已经围绕 API 构建了工作流但缺少必要数据的团队的要求,我们添加了诸如 profiles.transferred、profiles.deleted 和 profiles.proxy_changed 等事件。事件列表将继续扩大。
除了上述使用案例外,操作日志还可以用于其他任务:
账单和内部结算:来自
profiles.stopped的run_duration提供了准确的会话时长。如果您根据员工使用配置文件的实际工作时间来向其计费,而无需单独的时间跟踪器,这将非常有用。删除审计:
profiles.deleted和profiles.trashed与user_email结合使用,让您可以快速找出是谁在何时删除了特定的配置文件,而无需询问团队。配置文件转移跟踪:
profiles.transferred在单个记录中包含双方信息(发送者和接收者),因此无需匹配来自不同来源的数据。数据丢失通知:
profiles.force_stopped意味着正在运行的配置文件由于未正常关闭而被移至非活动状态。强制停止时在配置文件中进行的工作不会同步,因此应警告正在使用该配置文件的同事其更改将不会被保存。在我们的文档中了解更多信息。代理变更跟踪:
proxy_assigned/proxy_unassigned/proxy_changed适用于外部系统需要知道配置文件当前的代理而无需定期对其进行轮询的场景。
有一个重要的限制:操作日志以流的形式工作,并且仅存储过去 24 小时的数据。因此,如果您需要将事件用于审计或长期分析,则需要在它们到达时将其保存在您自己的系统中。
现在让我们来看看可用的事件以及如何使用它们。
Octo Browser 中的操作日志如何工作
类型:WebSocket
URL:
wss://app.octobrowser.net/api/v2/automation/ws/action_log授权:
X-Octo-Api-Token请求头中的 token
连接后,服务器会在事件发生时自动发送事件——不需要重复请求。每条消息都是一个 StreamPage:包含事件数组和一个 watermark。
{ "items": [ { "uuid": "550e8400-e29b-41d4-a716-446655440000", "action": "profiles.started", "time": 1707053400, "user_email": "user@example.com", "object_type": "profile", "object_id": "a1b2c3d4e5f67890abcdef1234567890", "object_title": "Octo Browser Profile", "data": { "connection_data": { "ip": "203.0.113.42", "countryCode": "FR", "countryName": "France", "subdivisions": ["Île-de-France", "Paris"], "postalCode": "75008", "cityName": "Paris", "timezone": "Europe/Paris", "lat": 48.8566, "lon": 2.3522, "languages": ["fr", "en-US", "en"], "isp": "Example Networks Ltd", "connectionType": "Cable/DSL" } } } ], "watermark": { "uuid": "550e8400-e29b-41d4-a716-446655440000", "time": 1707053400 } }
{ "items": [ { "uuid": "550e8400-e29b-41d4-a716-446655440000", "action": "profiles.started", "time": 1707053400, "user_email": "user@example.com", "object_type": "profile", "object_id": "a1b2c3d4e5f67890abcdef1234567890", "object_title": "Octo Browser Profile", "data": { "connection_data": { "ip": "203.0.113.42", "countryCode": "FR", "countryName": "France", "subdivisions": ["Île-de-France", "Paris"], "postalCode": "75008", "cityName": "Paris", "timezone": "Europe/Paris", "lat": 48.8566, "lon": 2.3522, "languages": ["fr", "en-US", "en"], "isp": "Example Networks Ltd", "connectionType": "Cable/DSL" } } } ], "watermark": { "uuid": "550e8400-e29b-41d4-a716-446655440000", "time": 1707053400 } }
操作日志目前支持十种事件类型:
profiles.started— 配置文件已启动;profiles.stopped— 配置文件已停止;profiles.force_stopped— 配置文件已被强制停止;profiles.transferred— 配置文件已转移给另一位用户;profiles.trashed— 配置文件已移至废纸篓;profiles.deleted— 配置文件已删除;profiles.updated— 配置文件已更新;profiles.proxy_assigned— 代理已分配给配置文件;profiles.proxy_unassigned— 代理已从配置文件中移除;profiles.proxy_changed— 代理已更换为另一个。
为了处理连接中断,每条消息都包含一个 watermark —— 最新事件的 UUID 和时间戳。重新连接时,只需在 after_uuid 参数中传递此 UUID:流将发送在停机期间发生的所有事情,而不会丢失或重复事件。另一个选择是使用 from_timestamp 从特定的时间点开始。只有一个限制:事件仅存储 24 小时。这是一个实时流,而不是存档。
这也适用于批量操作:如果员工一次性将 100 个配置文件移至废纸篓,所有 100 个事件都会出现在流中,每个事件都有自己的 object_id——不会有任何事件丢失或重复。
您可以在此处了解更多关于操作日志如何工作的信息。
数据(data)中包含什么 — 逐个事件分解
data 内部的字段取决于 action。以下是这十种类型中每种类型所提供的内容:
事件 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 带有 |
profiles.stopped
会话时长以 ISO 8601 格式提供,而不是以秒数提供:
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
profiles.updated
changeset 不是固定的字段列表,而是一个动态字段:它仅包含这次更改的内容。例如,当同时更改多个配置文件设置时,您会得到:
{ "action": "profiles.updated", "data": { "changeset": { "description": { "old_value": "", "new_value": "Test action log" }, "start_pages": { "added": ["http://google.com", "http://facebook.com"], "removed": [] }, "storage_options": { "added": ["serviceworkers", "localstorage"], "removed": [] }, "bookmarks": { "added": ["https://ebay.com", "https://amazon.com"], "removed": [] }, "launch_args": { "added": ["--start-maximized"], "removed": [] }, "images_load_limit": { "old_value": null, "new_value": 10240 }, "local_cache": { "old_value": false, "new_value": true }, "fingerprint": {} } } }
{ "action": "profiles.updated", "data": { "changeset": { "description": { "old_value": "", "new_value": "Test action log" }, "start_pages": { "added": ["http://google.com", "http://facebook.com"], "removed": [] }, "storage_options": { "added": ["serviceworkers", "localstorage"], "removed": [] }, "bookmarks": { "added": ["https://ebay.com", "https://amazon.com"], "removed": [] }, "launch_args": { "added": ["--start-maximized"], "removed": [] }, "images_load_limit": { "old_value": null, "new_value": 10240 }, "local_cache": { "old_value": false, "new_value": true }, "fingerprint": {} } } }
您可以看到两种模式:
对于单个值(
description、images_load_limit、local_cache),提供了一对old_value/new_value;对于列表(
start_pages、storage_options、bookmarks、launch_args),提供了added/removed。
fingerprint 是一个例外:当指纹确实发生更改时,该键会出现,但它始终是一个空对象,没有其内部更改内容的详细信息。通用规则很简单:如果字段没有更改,其键就不会出现在 changeset 中。
profiles.deleted
{ "action": "profiles.deleted", "data": { "manual": true } }
{ "action": "profiles.deleted", "data": { "manual": true } }
profiles.proxy_changed
在单个事件中对比旧代理和新代理:
{ "action": "profiles.proxy_changed", "data": { "old_proxy_uuid": "370b0ce963194f68803a812dd42db4be", "old_proxy_title": "Netlabs GB England", "old_url": "socks5://user:pass@proxy.example.com:1080", "new_proxy_uuid": "9c51385c3e2b417d9b34fc305a49d4f6", "new_proxy_title": "Netlabs GB England Towcester", "new_url": "socks5://user:pass@proxy2.example.com:1080" } }
{ "action": "profiles.proxy_changed", "data": { "old_proxy_uuid": "370b0ce963194f68803a812dd42db4be", "old_proxy_title": "Netlabs GB England", "old_url": "socks5://user:pass@proxy.example.com:1080", "new_proxy_uuid": "9c51385c3e2b417d9b34fc305a49d4f6", "new_proxy_title": "Netlabs GB England Towcester", "new_url": "socks5://user:pass@proxy2.example.com:1080" } }
profiles.proxy_assigned 和 profiles.proxy_unassigned 返回相同的字段,但没有 old_ / new_ 前缀——每个事件包含一组字段,而不是进行对比。
temporary: true 字段是独立的,它意味着代理是通过快捷操作(例如,通过粘贴相应的行)添加的,而不是通过配置文件设置正常分配的。
profiles.trashed 与自动删除
profiles.trashed 附带空的 data,就像 force_stopped 一样。如果配置文件未被恢复或手动删除,它将在 72 小时后自动删除。在废纸篓文档中了解更多信息。
profiles.transferred
单个事件包含双方信息:
{ "action": "profiles.transferred", "user_email": "sender@example.com", "data": { "receiver": "receiver@example.com" } }
{ "action": "profiles.transferred", "user_email": "sender@example.com", "data": { "receiver": "receiver@example.com" } }
user_email — 与任何其他事件一样,这是执行操作的用户的电子邮件,即转移的发送者。
data.receiver — 接收者。
连接与重新连接
您可以使用任何支持 WebSocket 的客户端进行连接。
使用 Node.js,它看起来像这样:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
接收到的事件中每个字段的含义:
uuid — 事件本身的标识符,而不是配置文件的标识符;每条记录都是唯一的,即使在同一秒内发生多个事件也是如此;
action — 上述列表中的事件类型;
time — Unix 格式的事件时间;
user_email — 执行操作的用户的电子邮件地址;
object_type — 事件关联的对象类型;
object_id — 配置文件本身的标识符,与事件 UUID 分开;
object_title — 事件发生时配置文件的名称;
data — 取决于
action的详细信息,如上所述。
如果配置文件停止,将发送第二个事件——profiles.stopped,该事件带有新的 uuid,但 object_id 相同,因为它是同一个配置文件。您可以使用 object_id 将配置文件的所有事件关联到您这边的单个历史记录中——object_id 在配置文件的整个生命周期(从启动到删除)中都不会改变。
要在连接中断后恢复流,只需保存上一个接收到的 watermark 中的 uuid,并在 after_uuid 中传递它:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?after_uuid=UUID', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?after_uuid=UUID', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
连接将立即发送在该 UUID 之后发生的事件,然后继续作为常规流工作。您只需在下一次中断后再次指定 after_uuid 即可。
如果您没有保存的水印 — 例如,在长时间停机后,您只知道断开连接的大致时间,您可以使用 from_timestamp(Unix 时间,以秒为单位)从特定时间开始:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?from_timestamp=TIMESTAMP', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?from_timestamp=TIMESTAMP', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
如果您刚刚开始接触自动化,我们将在另一篇单独的文章中更详细地解释 Octo Browser API。
结论
操作日志让您可以将 Octo Browser 事件作为您自己基础设施的一部分:将它们发送到 CRM、访问控制系统、分析平台或其他内部工具。Octo 告诉您配置文件发生了什么,而您决定如何处理、存储和使用这些数据。
如果您有这方面的使用案例,请告诉我们!目前可用的许多事件都是专门为了响应使用 API 的团队的实际任务而添加的。
管理任意数量的账户,无需担心被封禁、重复操作和不必要的开支。
想以优惠价体验 Octo Browser 吗?
使用促销码 OCTOBLOG 即可享受任意订阅 7 折优惠。此优惠仅对新用户有效。
无需手动验证的访问权限
我们的一位客户让来自不同部门的员工使用 Octo Browser 配置文件。每位员工都通过与 Octo 配合使用的自定义扩展拥有自己的访问级别。在授予所需权限之前,系统需要知道当前是谁在操作特定的配置文件。
在没有操作日志的情况下,无法准确查看是谁启动了配置文件。访问级别系统只能依赖间接指标:它可以检测到配置文件正在被使用,但无法得知是谁在使用它。
当我们在操作日志中添加了 profiles.started: user_email 事件后,流程发生了变化,从而可以自动应用权限。这种“事件 → 权限”的关联成为了我们大多数客户内部自动化的基石。
这是一个持续运行的机制,对每次配置文件的启动进行实时响应。事件会即时处理并存储在客户自己的数据库中。
我们的客户只需要一名开发人员和大约一个小时的时间就能集成操作日志。操作日志是作为附加模块添加到他们现有的权限系统中的,而不需要从头开始重构流程。
团队账目统计:数秒搞定,无需数小时
另一位客户使用分布式团队处理大量账号:许多人和许多配置文件同时进行处理。在这种规模下,很容易失去对全局的掌控:每个人正在处理多少个配置文件、有多少个已准备就绪、分配了多少个、删除了多少个,以及由谁删除和原因为何。
在切换到自己的系统之前,该团队在电子表格中记录所有内容。任何团队现状的快照都需要手动查看标签和记录。收集最新数据需要花费几个小时到一整天的时间,而当报告准备好时,部分信息已经过时了。
在我们扩展了操作日志之后,客户构建了他们自己的 CRM,该系统通过 API 接收配置文件事件,并将它们整合到一个统一的视图中:每位员工正在处理多少个配置文件、有多少个已准备就绪、分配了多少个以及删除了多少个,每项操作都与执行该操作的人员和时间相关联。
所有数据都以计数器和状态的形式显示在仪表板上并自动更新。以前需要花费数小时准备的报告,现在只需 30 秒即可生成——您只需打开相关板块即可。
该系统是在没有内部开发人员的情况下,使用 AI 编程工具开发的。仅用了一周时间就创建了集成 API 的 CRM 实用版本。
操作日志的其他用途
Octo 的 API 可以处理不同的任务:实时运行控制、活动跟踪和内部流程自动化。在上述两种情况下,集成只需数小时或数天,而不是数月,并且不需要专门的开发团队。
在每个场景中,其原理都是相同的:Octo 实时发送配置文件活动事件,而客户的系统决定如何处理和存储这些事件以及将它们用于何处。
真正的客户需求在操作日志的开发中起着至关重要的作用。应已经围绕 API 构建了工作流但缺少必要数据的团队的要求,我们添加了诸如 profiles.transferred、profiles.deleted 和 profiles.proxy_changed 等事件。事件列表将继续扩大。
除了上述使用案例外,操作日志还可以用于其他任务:
账单和内部结算:来自
profiles.stopped的run_duration提供了准确的会话时长。如果您根据员工使用配置文件的实际工作时间来向其计费,而无需单独的时间跟踪器,这将非常有用。删除审计:
profiles.deleted和profiles.trashed与user_email结合使用,让您可以快速找出是谁在何时删除了特定的配置文件,而无需询问团队。配置文件转移跟踪:
profiles.transferred在单个记录中包含双方信息(发送者和接收者),因此无需匹配来自不同来源的数据。数据丢失通知:
profiles.force_stopped意味着正在运行的配置文件由于未正常关闭而被移至非活动状态。强制停止时在配置文件中进行的工作不会同步,因此应警告正在使用该配置文件的同事其更改将不会被保存。在我们的文档中了解更多信息。代理变更跟踪:
proxy_assigned/proxy_unassigned/proxy_changed适用于外部系统需要知道配置文件当前的代理而无需定期对其进行轮询的场景。
有一个重要的限制:操作日志以流的形式工作,并且仅存储过去 24 小时的数据。因此,如果您需要将事件用于审计或长期分析,则需要在它们到达时将其保存在您自己的系统中。
现在让我们来看看可用的事件以及如何使用它们。
Octo Browser 中的操作日志如何工作
类型:WebSocket
URL:
wss://app.octobrowser.net/api/v2/automation/ws/action_log授权:
X-Octo-Api-Token请求头中的 token
连接后,服务器会在事件发生时自动发送事件——不需要重复请求。每条消息都是一个 StreamPage:包含事件数组和一个 watermark。
{ "items": [ { "uuid": "550e8400-e29b-41d4-a716-446655440000", "action": "profiles.started", "time": 1707053400, "user_email": "user@example.com", "object_type": "profile", "object_id": "a1b2c3d4e5f67890abcdef1234567890", "object_title": "Octo Browser Profile", "data": { "connection_data": { "ip": "203.0.113.42", "countryCode": "FR", "countryName": "France", "subdivisions": ["Île-de-France", "Paris"], "postalCode": "75008", "cityName": "Paris", "timezone": "Europe/Paris", "lat": 48.8566, "lon": 2.3522, "languages": ["fr", "en-US", "en"], "isp": "Example Networks Ltd", "connectionType": "Cable/DSL" } } } ], "watermark": { "uuid": "550e8400-e29b-41d4-a716-446655440000", "time": 1707053400 } }
操作日志目前支持十种事件类型:
profiles.started— 配置文件已启动;profiles.stopped— 配置文件已停止;profiles.force_stopped— 配置文件已被强制停止;profiles.transferred— 配置文件已转移给另一位用户;profiles.trashed— 配置文件已移至废纸篓;profiles.deleted— 配置文件已删除;profiles.updated— 配置文件已更新;profiles.proxy_assigned— 代理已分配给配置文件;profiles.proxy_unassigned— 代理已从配置文件中移除;profiles.proxy_changed— 代理已更换为另一个。
为了处理连接中断,每条消息都包含一个 watermark —— 最新事件的 UUID 和时间戳。重新连接时,只需在 after_uuid 参数中传递此 UUID:流将发送在停机期间发生的所有事情,而不会丢失或重复事件。另一个选择是使用 from_timestamp 从特定的时间点开始。只有一个限制:事件仅存储 24 小时。这是一个实时流,而不是存档。
这也适用于批量操作:如果员工一次性将 100 个配置文件移至废纸篓,所有 100 个事件都会出现在流中,每个事件都有自己的 object_id——不会有任何事件丢失或重复。
您可以在此处了解更多关于操作日志如何工作的信息。
数据(data)中包含什么 — 逐个事件分解
data 内部的字段取决于 action。以下是这十种类型中每种类型所提供的内容:
事件 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 带有 |
profiles.stopped
会话时长以 ISO 8601 格式提供,而不是以秒数提供:
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
profiles.updated
changeset 不是固定的字段列表,而是一个动态字段:它仅包含这次更改的内容。例如,当同时更改多个配置文件设置时,您会得到:
{ "action": "profiles.updated", "data": { "changeset": { "description": { "old_value": "", "new_value": "Test action log" }, "start_pages": { "added": ["http://google.com", "http://facebook.com"], "removed": [] }, "storage_options": { "added": ["serviceworkers", "localstorage"], "removed": [] }, "bookmarks": { "added": ["https://ebay.com", "https://amazon.com"], "removed": [] }, "launch_args": { "added": ["--start-maximized"], "removed": [] }, "images_load_limit": { "old_value": null, "new_value": 10240 }, "local_cache": { "old_value": false, "new_value": true }, "fingerprint": {} } } }
您可以看到两种模式:
对于单个值(
description、images_load_limit、local_cache),提供了一对old_value/new_value;对于列表(
start_pages、storage_options、bookmarks、launch_args),提供了added/removed。
fingerprint 是一个例外:当指纹确实发生更改时,该键会出现,但它始终是一个空对象,没有其内部更改内容的详细信息。通用规则很简单:如果字段没有更改,其键就不会出现在 changeset 中。
profiles.deleted
{ "action": "profiles.deleted", "data": { "manual": true } }
profiles.proxy_changed
在单个事件中对比旧代理和新代理:
{ "action": "profiles.proxy_changed", "data": { "old_proxy_uuid": "370b0ce963194f68803a812dd42db4be", "old_proxy_title": "Netlabs GB England", "old_url": "socks5://user:pass@proxy.example.com:1080", "new_proxy_uuid": "9c51385c3e2b417d9b34fc305a49d4f6", "new_proxy_title": "Netlabs GB England Towcester", "new_url": "socks5://user:pass@proxy2.example.com:1080" } }
profiles.proxy_assigned 和 profiles.proxy_unassigned 返回相同的字段,但没有 old_ / new_ 前缀——每个事件包含一组字段,而不是进行对比。
temporary: true 字段是独立的,它意味着代理是通过快捷操作(例如,通过粘贴相应的行)添加的,而不是通过配置文件设置正常分配的。
profiles.trashed 与自动删除
profiles.trashed 附带空的 data,就像 force_stopped 一样。如果配置文件未被恢复或手动删除,它将在 72 小时后自动删除。在废纸篓文档中了解更多信息。
profiles.transferred
单个事件包含双方信息:
{ "action": "profiles.transferred", "user_email": "sender@example.com", "data": { "receiver": "receiver@example.com" } }
user_email — 与任何其他事件一样,这是执行操作的用户的电子邮件,即转移的发送者。
data.receiver — 接收者。
连接与重新连接
您可以使用任何支持 WebSocket 的客户端进行连接。
使用 Node.js,它看起来像这样:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
接收到的事件中每个字段的含义:
uuid — 事件本身的标识符,而不是配置文件的标识符;每条记录都是唯一的,即使在同一秒内发生多个事件也是如此;
action — 上述列表中的事件类型;
time — Unix 格式的事件时间;
user_email — 执行操作的用户的电子邮件地址;
object_type — 事件关联的对象类型;
object_id — 配置文件本身的标识符,与事件 UUID 分开;
object_title — 事件发生时配置文件的名称;
data — 取决于
action的详细信息,如上所述。
如果配置文件停止,将发送第二个事件——profiles.stopped,该事件带有新的 uuid,但 object_id 相同,因为它是同一个配置文件。您可以使用 object_id 将配置文件的所有事件关联到您这边的单个历史记录中——object_id 在配置文件的整个生命周期(从启动到删除)中都不会改变。
要在连接中断后恢复流,只需保存上一个接收到的 watermark 中的 uuid,并在 after_uuid 中传递它:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?after_uuid=UUID', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
连接将立即发送在该 UUID 之后发生的事件,然后继续作为常规流工作。您只需在下一次中断后再次指定 after_uuid 即可。
如果您没有保存的水印 — 例如,在长时间停机后,您只知道断开连接的大致时间,您可以使用 from_timestamp(Unix 时间,以秒为单位)从特定时间开始:
const WebSocket = require('ws'); const ws = new WebSocket('wss://app.octobrowser.net/api/v2/automation/ws/action_log?from_timestamp=TIMESTAMP', { headers: { 'X-Octo-Api-Token': 'Octo API Token' } }); ws.on('open', () => console.log('Connected!')); ws.on('message', (data) => { const parsed = JSON.parse(data.toString()); console.log(JSON.stringify(parsed, null, 2)); console.log(''); }); ws.on('error', (err) => console.log('Error:', err.message)); ws.on('close', () => console.log('Connection closed'));
如果您刚刚开始接触自动化,我们将在另一篇单独的文章中更详细地解释 Octo Browser API。
结论
操作日志让您可以将 Octo Browser 事件作为您自己基础设施的一部分:将它们发送到 CRM、访问控制系统、分析平台或其他内部工具。Octo 告诉您配置文件发生了什么,而您决定如何处理、存储和使用这些数据。
如果您有这方面的使用案例,请告诉我们!目前可用的许多事件都是专门为了响应使用 API 的团队的实际任务而添加的。
随时获取最新的Octo Browser新闻
通过点击按钮,您同意我们的 隐私政策。
随时获取最新的Octo Browser新闻
通过点击按钮,您同意我们的 隐私政策。
随时获取最新的Octo Browser新闻
通过点击按钮,您同意我们的 隐私政策。

