Nhật kí hành động API: cách khách hàng sử dụng các sự kiện hồ sơ trong quy trình làm việc của riêng họ


Alex Phillips
Customer Service Specialist
Giao diện tiêu chuẩn của Octo Browser hiển thị cho bạn những gì đang diễn ra với hồ sơ của bạn ngay lúc này. Nhưng khi một nhóm quản lý hàng trăm hoặc hàng nghìn hồ sơ, đến một lúc nào đó họ cần tự động gửi các sự kiện hồ sơ đến CRM, hệ thống kiểm soát truy cập hoặc bảng điều khiển nội bộ.
Đó chính là mục đích của Nhật kí hành động của Octo: một điểm cuối WebSocket gửi các sự kiện trong thời gian thực. Chúng tôi đã thêm tính năng này cho các nhóm đã tích hợp Octo vào CRM, ERP hoặc hệ thống kế toán của riêng họ. Hiện tại, Nhật kí hành động của Octo hỗ trợ mười loại sự kiện—từ việc khởi chạy và dừng hồ sơ cho đến chuyển giao, xóa và thay đổi proxy—và danh sách này đang tiếp tục tăng lên khi các nhóm khám phá ra các trường hợp sử dụng mới.
Dưới đây, bạn có thể tìm thấy hai ví dụ về cách bạn có thể sử dụng Nhật kí hành động trong thực tế: kiểm soát truy cập theo thời gian thực và quản lý tài khoản ở quy mô lớn.
Nội dung
Quản lí số lượng tài khoản không giới hạn mà không lo bị chặn, hoạt động thường nhật, hay lo tới các chi phí không đáng có.
Bạn có muốn trải nghiệm Octo Browser với giá ưu đãi?
Hãy nhập mã khuyến mãi OCTOBLOG để được giảm giá 30% cho bất kỳ gói đăng ký nào. Ưu đãi này chỉ áp dụng cho người dùng mới.
Quyền truy cập không cần xác minh thủ công
Một khách hàng của chúng tôi có nhân viên từ các bộ phận khác nhau cùng làm việc trên các hồ sơ Octo Browser. Mỗi nhân viên có mức truy cập riêng thông qua một tiện ích mở rộng tùy chỉnh được sử dụng cùng với Octo. Trước khi cấp các quyền cần thiết, hệ thống cần biết ai hiện đang làm việc với một hồ sơ cụ thể.
Nếu không có Nhật kí hành động, không có cách nào để biết chính xác ai đã khởi chạy hồ sơ. Hệ thống phân quyền truy cập phải dựa vào các chỉ số gián tiếp: nó có thể phát hiện một hồ sơ đang được sử dụng, nhưng không biết ai là người đang sử dụng.
Quy trình này đã thay đổi khi chúng tôi thêm sự kiện profiles.started: user_email vào Nhật kí hành động, nhờ đó các quyền có thể được áp dụng tự động. Mối liên kết giữa sự kiện → quyền truy cập này đã trở thành nền tảng cho hầu hết các quy trình tự động hóa nội bộ của khách hàng chúng tôi.
Đây là một cơ chế chạy liên tục để phản hồi mọi hoạt động khởi chạy hồ sơ trong thời gian thực. Các sự kiện được xử lý nhanh chóng và được lưu trữ trong cơ sở dữ liệu riêng của khách hàng.
Khách hàng của chúng tôi chỉ cần một lập trình viên và khoảng một giờ để tích hợp Nhật kí hành động. Nhật kí hành động đã được thêm vào hệ thống phân quyền hiện tại của họ như một mô-đun bổ sung thay vì yêu cầu phải xây dựng lại quy trình từ đầu.
Thống kê công việc của nhóm trong vài giây thay vì hàng giờ
Một khách hàng khác làm việc với một số lượng lớn tài khoản bằng cách phân chia nhân sự: nhiều người và nhiều hồ sơ được xử lý đồng thời. Ở quy mô này, rất dễ mất đi cái nhìn tổng quan: mỗi người đang xử lý bao nhiêu hồ sơ, bao nhiêu hồ sơ đã sẵn sàng, bao nhiêu hồ sơ đã được bàn giao, bao nhiêu hồ sơ đã bị xóa, bởi ai và vì lý do gì.
Trước khi chuyển sang hệ thống riêng của mình, nhóm này đã theo dõi mọi thứ bằng bảng tính. Bất kỳ số liệu báo cáo nhanh nào của nhóm cũng đều yêu cầu phải rà soát thủ công qua các thẻ và bản ghi. Việc thu thập dữ liệu cập nhật mất từ vài giờ đến cả ngày, và đến khi báo cáo sẵn sàng thì một số thông tin đã trở nên lỗi thời.
Sau khi chúng tôi mở rộng Nhật kí hành động, khách hàng đã xây dựng hệ thống CRM của riêng họ để nhận các sự kiện hồ sơ thông qua API và tập hợp chúng lại thành một giao diện tổng quan duy nhất: mỗi nhân viên đang làm việc trên bao nhiêu hồ sơ, bao nhiêu hồ sơ đã sẵn sàng, bao nhiêu hồ sơ đã được bàn giao, và bao nhiêu hồ sơ đã bị xóa, với mỗi hành động được liên kết với người thực hiện và thời gian cụ thể.
Tất cả dữ liệu được hiển thị trên một bảng điều khiển dưới dạng các bộ đếm và trạng thái, đồng thời được cập nhật tự động. Một báo cáo trước đây phải mất hàng giờ để chuẩn bị thì giờ đây có thể được tạo ra trong 30 giây—tất cả những gì bạn cần làm là mở phần tương ứng.
Hệ thống này được phát triển mà không cần lập trình viên nội bộ, mà sử dụng các công cụ lập trình AI. Chỉ mất một tuần để tạo ra một phiên bản CRM hoạt động được có tích hợp API.
Những cách sử dụng Nhật kí hành động khác
API của Octo có thể xử lý các tác vụ khác nhau: kiểm soát vận hành theo thời gian thực, theo dõi hoạt động và tự động hóa quy trình nội bộ. Trong cả hai trường hợp được mô tả ở trên, việc tích hợp chỉ mất vài giờ hoặc vài ngày thay vì vài tháng và không yêu cầu một đội ngũ phát triển chuyên trách.
Nguyên lý hoạt động đều giống nhau trong mọi tình huống: Octo gửi các sự kiện hoạt động của hồ sơ trong thời gian thực, trong khi hệ thống của khách hàng quyết định cách xử lý, lưu trữ và mục đích sử dụng chúng.
Nhu cầu thực tế của khách hàng đóng vai trò lớn trong việc phát triển Nhật kí hành động. Các sự kiện như profiles.transferred, profiles.deleted, và profiles.proxy_changed cùng nhiều sự kiện khác đã được thêm vào theo yêu cầu của các nhóm đã xây dựng quy trình làm việc xung quanh API nhưng thiếu dữ liệu cần thiết. Danh sách các sự kiện sẽ tiếp tục được mở rộng.
Ngoài các trường hợp sử dụng được mô tả ở trên, Nhật kí hành động còn có thể được sử dụng cho các tác vụ khác:
Hoá đơn và tính toán nội bộ:
run_durationtừprofiles.stoppedcung cấp thời lượng phiên chính xác, hữu ích nếu bạn tính lương cho nhân viên dựa trên thời gian làm việc thực tế của họ với một hồ sơ, mà không cần một trình theo dõi thời gian riêng biệt.Kiểm tra việc xóa:
profiles.deletedvàprofiles.trashed, cùng vớiuser_email, cho phép bạn nhanh chóng tìm ra ai đã xóa một hồ sơ cụ thể và vào lúc nào, mà không cần phải hỏi nhóm.Theo dõi chuyển giao hồ sơ:
profiles.transferredchứa thông tin của cả hai bên trong một bản ghi duy nhất (người gửi và người nhận) nên không cần phải đối chiếu dữ liệu từ các nguồn khác nhau.Thông báo mất dữ liệu:
profiles.force_stoppedcó nghĩa là một hồ sơ đang chạy đã bị chuyển sang trạng thái không hoạt động vì không được đóng bình thường. Công việc được thực hiện trong hồ sơ tại thời điểm bị buộc dừng sẽ không được đồng bộ hóa, vì vậy cần cảnh báo cho các đồng nghiệp đang làm việc với hồ sơ đó rằng các thay đổi của họ sẽ không được lưu. Tìm hiểu thêm trong tài liệu của chúng tôi.Theo dõi thay đổi proxy:
proxy_assigned/proxy_unassigned/proxy_changedphù hợp cho các tình huống mà hệ thống bên ngoài cần biết proxy hiện tại của hồ sơ mà không cần phải thăm dò định kỳ.
Có một giới hạn quan trọng cần lưu ý: Nhật kí hành động hoạt động dưới dạng luồng dữ liệu (stream) và chỉ lưu trữ dữ liệu trong vòng 24 giờ qua. Do đó, nếu bạn cần các sự kiện để kiểm tra hoặc phân tích dài hạn, bạn cần lưu chúng vào hệ thống riêng của mình ngay khi chúng được gửi đến.
Bây giờ chúng ta hãy cùng xem các sự kiện hiện có và cách làm việc với chúng.
Cách hoạt động của Nhật kí hành động trong Octo Browser
Loại: WebSocket
URL:
wss://app.octobrowser.net/api/v2/automation/ws/action_logXác thực: token trong tiêu đề
X-Octo-Api-Token
Sau khi kết nối, máy chủ sẽ tự động gửi các sự kiện khi chúng xảy ra—không cần yêu cầu lặp lại. Mỗi tin nhắn là một StreamPage: một mảng các sự kiện và một 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 } }
Nhật kí hành động hiện hỗ trợ mười loại sự kiện:
profiles.started— hồ sơ đã được khởi chạy;profiles.stopped— hồ sơ đã dừng;profiles.force_stopped— hồ sơ bị buộc dừng;profiles.transferred— hồ sơ được chuyển sang cho người dùng khác;profiles.trashed— hồ sơ đã được đưa vào thùng rác;profiles.deleted— hồ sơ đã bị xóa;profiles.updated— hồ sơ đã được cập nhật;profiles.proxy_assigned— proxy được gán cho hồ sơ;profiles.proxy_unassigned— proxy bị gỡ bỏ khỏi hồ sơ;profiles.proxy_changed— proxy được thay đổi sang cái khác.
Để xử lý các trường hợp gián đoạn kết nối, mỗi tin nhắn chứa một watermark — UUID và mốc thời gian của sự kiện mới nhất. Khi kết nối lại, bạn chỉ cần truyền UUID này vào tham số after_uuid: luồng dữ liệu sẽ gửi tất cả những gì đã xảy ra trong thời gian ngoại tuyến mà không làm mất hoặc trùng lặp các sự kiện. Một tùy chọn khác là bắt đầu từ một thời điểm cụ thể bằng cách sử dụng from_timestamp. Chỉ có một giới hạn duy nhất: các sự kiện được lưu trữ trong 24 giờ. Đây là một luồng dữ liệu trực tiếp, không phải là kho lưu trữ.
Điều này cũng hoạt động với các thao tác hàng loạt: nếu một nhân viên chuyển cùng lúc 100 hồ sơ vào thùng rác, tất cả 100 sự kiện sẽ xuất hiện trong luồng dữ liệu, mỗi sự kiện có object_id riêng—không có sự kiện nào bị mất hoặc bị lặp lại.
Bạn có thể tìm hiểu thêm về cách hoạt động của Nhật kí hành động tại đây.
Chi tiết trong data — phân tích từng sự kiện
Các trường bên trong data tùy thuộc vào action. Dưới đây là những gì được cung cấp cho mỗi loại trong mười loại sự kiện:
Sự kiện | Chi tiết trong |
|
|
|
|
|
|
|
|
|
|
|
|
| các trường tương tự với tiền tố |
profiles.stopped
Thời lượng phiên được cung cấp theo định dạng ISO 8601, thay vì dưới dạng số giây:
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
profiles.updated
changeset không phải là một danh sách cố định các trường, mà là một trường động: nó chỉ chứa những gì đã thay đổi lần này. Ví dụ, khi một vài cài đặt hồ sơ được thay đổi cùng lúc, bạn sẽ nhận được:
{ "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": {} } } }
Bạn có thể thấy hai quy luật:
đối với các giá trị riêng lẻ (
description,images_load_limit,local_cache), một cặpold_value/new_valueđược cung cấp;đối với danh sách (
start_pages,storage_options,bookmarks,launch_args), các mụcadded/removedđược cung cấp.
fingerprint là một ngoại lệ: khóa này xuất hiện khi vân tay thực sự thay đổi, nhưng nó luôn là một đối tượng trống, không hiển thị chi tiết các thay đổi bên trong. Quy tắc chung rất đơn giản: nếu một trường không thay đổi, khóa của nó sẽ không xuất hiện trong changeset.
profiles.deleted
{ "action": "profiles.deleted", "data": { "manual": true } }
{ "action": "profiles.deleted", "data": { "manual": true } }
profiles.proxy_changed
So sánh các proxy cũ và mới trong một sự kiện duy nhất:
{ "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 và profiles.proxy_unassigned trả về các trường tương tự, nhưng không có các tiền tố old_ / new_ — một tập hợp các trường cho mỗi sự kiện thay vì một phép so sánh.
Trường temporary: true là riêng biệt và nó có nghĩa là proxy được thêm thông qua một thao tác nhanh (ví dụ, bằng cách dán một dòng tương ứng) chứ không phải được chỉ định thông thường thông qua các cài đặt hồ sơ.
profiles.trashed và tự động xóa
profiles.trashed đi kèm với data trống, giống như force_stopped. Nếu hồ sơ không được khôi phục hoặc xóa thủ công, nó sẽ tự động bị xóa sau 72 giờ. Tìm hiểu thêm trong tài liệu về thùng rác.
profiles.transferred
Một sự kiện duy nhất chứa thông tin của cả hai bên:
{ "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 — như trong bất kỳ sự kiện nào khác, đây là email của người dùng đã thực hiện hành động, tức là người gửi của quá trình chuyển giao.
data.receiver — người nhận.
Kết nối và kết nối lại
Bạn có thể kết nối bằng bất kỳ ứng dụng khách nào hỗ trợ WebSocket.
Sử dụng Node.js, mã sẽ trông như thế này:
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'));
Ý nghĩa của từng trường trong sự kiện nhận được:
uuid — số nhận dạng của chính sự kiện đó, không phải của hồ sơ; là duy nhất cho mỗi bản ghi, ngay cả khi có nhiều sự kiện xảy ra trong cùng một giây;
action — loại hành động từ danh sách ở trên;
time — thời gian diễn ra sự kiện theo định dạng Unix;
user_email — địa chỉ email của người dùng đã thực hiện hành động;
object_type — loại đối tượng mà sự kiện liên quan đến;
object_id — số nhận dạng của chính hồ sơ đó, tách biệt với UUID của sự kiện;
object_title — tên hồ sơ tại thời điểm diễn ra sự kiện;
data — chi tiết phụ thuộc vào
action, như đã mô tả ở trên.
Nếu một hồ sơ bị dừng, sự kiện thứ hai—profiles.stopped—báo hiệu việc dừng hồ sơ sẽ được gửi với một uuid mới nhưng vẫn giữ nguyên object_id, vì đó là cùng một hồ sơ. Bạn có thể sử dụng object_id để liên kết tất cả các sự kiện của một hồ sơ thành một lịch sử duy nhất ở phía bạn—object_id không thay đổi trong suốt vòng đời của hồ sơ, từ khi khởi chạy cho đến khi bị xóa.
Để tiếp tục luồng dữ liệu sau khi kết nối bị gián đoạn, chỉ cần lưu uuid từ watermark nhận được gần nhất và truyền nó vào 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'));
Kết nối sẽ ngay lập tức gửi các sự kiện đã xảy ra sau UUID này và sau đó tiếp tục hoạt động như một luồng dữ liệu thông thường. Bạn chỉ cần chỉ định lại after_uuid sau lần gián đoạn tiếp theo.
Nếu bạn không lưu watermark — ví dụ, sau một thời gian dài ngoại tuyến và bạn chỉ biết thời gian ước tính của lần ngắt kết nối, bạn có thể bắt đầu từ một thời điểm cụ thể bằng cách sử dụng from_timestamp (thời gian Unix tính bằng giây):
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'));
Nếu bạn chỉ mới bắt đầu với tự động hóa, chúng tôi sẽ giải thích chi tiết hơn về API của Octo Browser trong một bài viết riêng biệt.
Kết luận
Nhật kí hành động cho phép bạn sử dụng các sự kiện của Octo Browser như một phần trong hạ tầng của riêng bạn: gửi chúng đến hệ thống CRM, hệ thống kiểm soát truy cập, nền tảng phân tích hoặc các công cụ nội bộ khác. Octo cho bạn biết những gì đã xảy ra với một hồ sơ, và bạn quyết định cách xử lý, lưu trữ và sử dụng dữ liệu đó.
Nếu bạn có một trường hợp sử dụng thực tế cho tính năng này, hãy chia sẻ với chúng tôi! Nhiều sự kiện hiện có ngày hôm nay đã được thêm vào nhằm phản hồi trực tiếp các tác vụ thực tế từ các nhóm đang làm việc với API.
Quản lí số lượng tài khoản không giới hạn mà không lo bị chặn, hoạt động thường nhật, hay lo tới các chi phí không đáng có.
Bạn có muốn trải nghiệm Octo Browser với giá ưu đãi?
Hãy nhập mã khuyến mãi OCTOBLOG để được giảm giá 30% cho bất kỳ gói đăng ký nào. Ưu đãi này chỉ áp dụng cho người dùng mới.
Quyền truy cập không cần xác minh thủ công
Một khách hàng của chúng tôi có nhân viên từ các bộ phận khác nhau cùng làm việc trên các hồ sơ Octo Browser. Mỗi nhân viên có mức truy cập riêng thông qua một tiện ích mở rộng tùy chỉnh được sử dụng cùng với Octo. Trước khi cấp các quyền cần thiết, hệ thống cần biết ai hiện đang làm việc với một hồ sơ cụ thể.
Nếu không có Nhật kí hành động, không có cách nào để biết chính xác ai đã khởi chạy hồ sơ. Hệ thống phân quyền truy cập phải dựa vào các chỉ số gián tiếp: nó có thể phát hiện một hồ sơ đang được sử dụng, nhưng không biết ai là người đang sử dụng.
Quy trình này đã thay đổi khi chúng tôi thêm sự kiện profiles.started: user_email vào Nhật kí hành động, nhờ đó các quyền có thể được áp dụng tự động. Mối liên kết giữa sự kiện → quyền truy cập này đã trở thành nền tảng cho hầu hết các quy trình tự động hóa nội bộ của khách hàng chúng tôi.
Đây là một cơ chế chạy liên tục để phản hồi mọi hoạt động khởi chạy hồ sơ trong thời gian thực. Các sự kiện được xử lý nhanh chóng và được lưu trữ trong cơ sở dữ liệu riêng của khách hàng.
Khách hàng của chúng tôi chỉ cần một lập trình viên và khoảng một giờ để tích hợp Nhật kí hành động. Nhật kí hành động đã được thêm vào hệ thống phân quyền hiện tại của họ như một mô-đun bổ sung thay vì yêu cầu phải xây dựng lại quy trình từ đầu.
Thống kê công việc của nhóm trong vài giây thay vì hàng giờ
Một khách hàng khác làm việc với một số lượng lớn tài khoản bằng cách phân chia nhân sự: nhiều người và nhiều hồ sơ được xử lý đồng thời. Ở quy mô này, rất dễ mất đi cái nhìn tổng quan: mỗi người đang xử lý bao nhiêu hồ sơ, bao nhiêu hồ sơ đã sẵn sàng, bao nhiêu hồ sơ đã được bàn giao, bao nhiêu hồ sơ đã bị xóa, bởi ai và vì lý do gì.
Trước khi chuyển sang hệ thống riêng của mình, nhóm này đã theo dõi mọi thứ bằng bảng tính. Bất kỳ số liệu báo cáo nhanh nào của nhóm cũng đều yêu cầu phải rà soát thủ công qua các thẻ và bản ghi. Việc thu thập dữ liệu cập nhật mất từ vài giờ đến cả ngày, và đến khi báo cáo sẵn sàng thì một số thông tin đã trở nên lỗi thời.
Sau khi chúng tôi mở rộng Nhật kí hành động, khách hàng đã xây dựng hệ thống CRM của riêng họ để nhận các sự kiện hồ sơ thông qua API và tập hợp chúng lại thành một giao diện tổng quan duy nhất: mỗi nhân viên đang làm việc trên bao nhiêu hồ sơ, bao nhiêu hồ sơ đã sẵn sàng, bao nhiêu hồ sơ đã được bàn giao, và bao nhiêu hồ sơ đã bị xóa, với mỗi hành động được liên kết với người thực hiện và thời gian cụ thể.
Tất cả dữ liệu được hiển thị trên một bảng điều khiển dưới dạng các bộ đếm và trạng thái, đồng thời được cập nhật tự động. Một báo cáo trước đây phải mất hàng giờ để chuẩn bị thì giờ đây có thể được tạo ra trong 30 giây—tất cả những gì bạn cần làm là mở phần tương ứng.
Hệ thống này được phát triển mà không cần lập trình viên nội bộ, mà sử dụng các công cụ lập trình AI. Chỉ mất một tuần để tạo ra một phiên bản CRM hoạt động được có tích hợp API.
Những cách sử dụng Nhật kí hành động khác
API của Octo có thể xử lý các tác vụ khác nhau: kiểm soát vận hành theo thời gian thực, theo dõi hoạt động và tự động hóa quy trình nội bộ. Trong cả hai trường hợp được mô tả ở trên, việc tích hợp chỉ mất vài giờ hoặc vài ngày thay vì vài tháng và không yêu cầu một đội ngũ phát triển chuyên trách.
Nguyên lý hoạt động đều giống nhau trong mọi tình huống: Octo gửi các sự kiện hoạt động của hồ sơ trong thời gian thực, trong khi hệ thống của khách hàng quyết định cách xử lý, lưu trữ và mục đích sử dụng chúng.
Nhu cầu thực tế của khách hàng đóng vai trò lớn trong việc phát triển Nhật kí hành động. Các sự kiện như profiles.transferred, profiles.deleted, và profiles.proxy_changed cùng nhiều sự kiện khác đã được thêm vào theo yêu cầu của các nhóm đã xây dựng quy trình làm việc xung quanh API nhưng thiếu dữ liệu cần thiết. Danh sách các sự kiện sẽ tiếp tục được mở rộng.
Ngoài các trường hợp sử dụng được mô tả ở trên, Nhật kí hành động còn có thể được sử dụng cho các tác vụ khác:
Hoá đơn và tính toán nội bộ:
run_durationtừprofiles.stoppedcung cấp thời lượng phiên chính xác, hữu ích nếu bạn tính lương cho nhân viên dựa trên thời gian làm việc thực tế của họ với một hồ sơ, mà không cần một trình theo dõi thời gian riêng biệt.Kiểm tra việc xóa:
profiles.deletedvàprofiles.trashed, cùng vớiuser_email, cho phép bạn nhanh chóng tìm ra ai đã xóa một hồ sơ cụ thể và vào lúc nào, mà không cần phải hỏi nhóm.Theo dõi chuyển giao hồ sơ:
profiles.transferredchứa thông tin của cả hai bên trong một bản ghi duy nhất (người gửi và người nhận) nên không cần phải đối chiếu dữ liệu từ các nguồn khác nhau.Thông báo mất dữ liệu:
profiles.force_stoppedcó nghĩa là một hồ sơ đang chạy đã bị chuyển sang trạng thái không hoạt động vì không được đóng bình thường. Công việc được thực hiện trong hồ sơ tại thời điểm bị buộc dừng sẽ không được đồng bộ hóa, vì vậy cần cảnh báo cho các đồng nghiệp đang làm việc với hồ sơ đó rằng các thay đổi của họ sẽ không được lưu. Tìm hiểu thêm trong tài liệu của chúng tôi.Theo dõi thay đổi proxy:
proxy_assigned/proxy_unassigned/proxy_changedphù hợp cho các tình huống mà hệ thống bên ngoài cần biết proxy hiện tại của hồ sơ mà không cần phải thăm dò định kỳ.
Có một giới hạn quan trọng cần lưu ý: Nhật kí hành động hoạt động dưới dạng luồng dữ liệu (stream) và chỉ lưu trữ dữ liệu trong vòng 24 giờ qua. Do đó, nếu bạn cần các sự kiện để kiểm tra hoặc phân tích dài hạn, bạn cần lưu chúng vào hệ thống riêng của mình ngay khi chúng được gửi đến.
Bây giờ chúng ta hãy cùng xem các sự kiện hiện có và cách làm việc với chúng.
Cách hoạt động của Nhật kí hành động trong Octo Browser
Loại: WebSocket
URL:
wss://app.octobrowser.net/api/v2/automation/ws/action_logXác thực: token trong tiêu đề
X-Octo-Api-Token
Sau khi kết nối, máy chủ sẽ tự động gửi các sự kiện khi chúng xảy ra—không cần yêu cầu lặp lại. Mỗi tin nhắn là một StreamPage: một mảng các sự kiện và một 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 } }
Nhật kí hành động hiện hỗ trợ mười loại sự kiện:
profiles.started— hồ sơ đã được khởi chạy;profiles.stopped— hồ sơ đã dừng;profiles.force_stopped— hồ sơ bị buộc dừng;profiles.transferred— hồ sơ được chuyển sang cho người dùng khác;profiles.trashed— hồ sơ đã được đưa vào thùng rác;profiles.deleted— hồ sơ đã bị xóa;profiles.updated— hồ sơ đã được cập nhật;profiles.proxy_assigned— proxy được gán cho hồ sơ;profiles.proxy_unassigned— proxy bị gỡ bỏ khỏi hồ sơ;profiles.proxy_changed— proxy được thay đổi sang cái khác.
Để xử lý các trường hợp gián đoạn kết nối, mỗi tin nhắn chứa một watermark — UUID và mốc thời gian của sự kiện mới nhất. Khi kết nối lại, bạn chỉ cần truyền UUID này vào tham số after_uuid: luồng dữ liệu sẽ gửi tất cả những gì đã xảy ra trong thời gian ngoại tuyến mà không làm mất hoặc trùng lặp các sự kiện. Một tùy chọn khác là bắt đầu từ một thời điểm cụ thể bằng cách sử dụng from_timestamp. Chỉ có một giới hạn duy nhất: các sự kiện được lưu trữ trong 24 giờ. Đây là một luồng dữ liệu trực tiếp, không phải là kho lưu trữ.
Điều này cũng hoạt động với các thao tác hàng loạt: nếu một nhân viên chuyển cùng lúc 100 hồ sơ vào thùng rác, tất cả 100 sự kiện sẽ xuất hiện trong luồng dữ liệu, mỗi sự kiện có object_id riêng—không có sự kiện nào bị mất hoặc bị lặp lại.
Bạn có thể tìm hiểu thêm về cách hoạt động của Nhật kí hành động tại đây.
Chi tiết trong data — phân tích từng sự kiện
Các trường bên trong data tùy thuộc vào action. Dưới đây là những gì được cung cấp cho mỗi loại trong mười loại sự kiện:
Sự kiện | Chi tiết trong |
|
|
|
|
|
|
|
|
|
|
|
|
| các trường tương tự với tiền tố |
profiles.stopped
Thời lượng phiên được cung cấp theo định dạng ISO 8601, thay vì dưới dạng số giây:
{ "action": "profiles.stopped", "data": { "run_duration": "PT19.627134S" } }
profiles.updated
changeset không phải là một danh sách cố định các trường, mà là một trường động: nó chỉ chứa những gì đã thay đổi lần này. Ví dụ, khi một vài cài đặt hồ sơ được thay đổi cùng lúc, bạn sẽ nhận được:
{ "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": {} } } }
Bạn có thể thấy hai quy luật:
đối với các giá trị riêng lẻ (
description,images_load_limit,local_cache), một cặpold_value/new_valueđược cung cấp;đối với danh sách (
start_pages,storage_options,bookmarks,launch_args), các mụcadded/removedđược cung cấp.
fingerprint là một ngoại lệ: khóa này xuất hiện khi vân tay thực sự thay đổi, nhưng nó luôn là một đối tượng trống, không hiển thị chi tiết các thay đổi bên trong. Quy tắc chung rất đơn giản: nếu một trường không thay đổi, khóa của nó sẽ không xuất hiện trong changeset.
profiles.deleted
{ "action": "profiles.deleted", "data": { "manual": true } }
profiles.proxy_changed
So sánh các proxy cũ và mới trong một sự kiện duy nhất:
{ "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 và profiles.proxy_unassigned trả về các trường tương tự, nhưng không có các tiền tố old_ / new_ — một tập hợp các trường cho mỗi sự kiện thay vì một phép so sánh.
Trường temporary: true là riêng biệt và nó có nghĩa là proxy được thêm thông qua một thao tác nhanh (ví dụ, bằng cách dán một dòng tương ứng) chứ không phải được chỉ định thông thường thông qua các cài đặt hồ sơ.
profiles.trashed và tự động xóa
profiles.trashed đi kèm với data trống, giống như force_stopped. Nếu hồ sơ không được khôi phục hoặc xóa thủ công, nó sẽ tự động bị xóa sau 72 giờ. Tìm hiểu thêm trong tài liệu về thùng rác.
profiles.transferred
Một sự kiện duy nhất chứa thông tin của cả hai bên:
{ "action": "profiles.transferred", "user_email": "sender@example.com", "data": { "receiver": "receiver@example.com" } }
user_email — như trong bất kỳ sự kiện nào khác, đây là email của người dùng đã thực hiện hành động, tức là người gửi của quá trình chuyển giao.
data.receiver — người nhận.
Kết nối và kết nối lại
Bạn có thể kết nối bằng bất kỳ ứng dụng khách nào hỗ trợ WebSocket.
Sử dụng Node.js, mã sẽ trông như thế này:
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'));
Ý nghĩa của từng trường trong sự kiện nhận được:
uuid — số nhận dạng của chính sự kiện đó, không phải của hồ sơ; là duy nhất cho mỗi bản ghi, ngay cả khi có nhiều sự kiện xảy ra trong cùng một giây;
action — loại hành động từ danh sách ở trên;
time — thời gian diễn ra sự kiện theo định dạng Unix;
user_email — địa chỉ email của người dùng đã thực hiện hành động;
object_type — loại đối tượng mà sự kiện liên quan đến;
object_id — số nhận dạng của chính hồ sơ đó, tách biệt với UUID của sự kiện;
object_title — tên hồ sơ tại thời điểm diễn ra sự kiện;
data — chi tiết phụ thuộc vào
action, như đã mô tả ở trên.
Nếu một hồ sơ bị dừng, sự kiện thứ hai—profiles.stopped—báo hiệu việc dừng hồ sơ sẽ được gửi với một uuid mới nhưng vẫn giữ nguyên object_id, vì đó là cùng một hồ sơ. Bạn có thể sử dụng object_id để liên kết tất cả các sự kiện của một hồ sơ thành một lịch sử duy nhất ở phía bạn—object_id không thay đổi trong suốt vòng đời của hồ sơ, từ khi khởi chạy cho đến khi bị xóa.
Để tiếp tục luồng dữ liệu sau khi kết nối bị gián đoạn, chỉ cần lưu uuid từ watermark nhận được gần nhất và truyền nó vào 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'));
Kết nối sẽ ngay lập tức gửi các sự kiện đã xảy ra sau UUID này và sau đó tiếp tục hoạt động như một luồng dữ liệu thông thường. Bạn chỉ cần chỉ định lại after_uuid sau lần gián đoạn tiếp theo.
Nếu bạn không lưu watermark — ví dụ, sau một thời gian dài ngoại tuyến và bạn chỉ biết thời gian ước tính của lần ngắt kết nối, bạn có thể bắt đầu từ một thời điểm cụ thể bằng cách sử dụng from_timestamp (thời gian Unix tính bằng giây):
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'));
Nếu bạn chỉ mới bắt đầu với tự động hóa, chúng tôi sẽ giải thích chi tiết hơn về API của Octo Browser trong một bài viết riêng biệt.
Kết luận
Nhật kí hành động cho phép bạn sử dụng các sự kiện của Octo Browser như một phần trong hạ tầng của riêng bạn: gửi chúng đến hệ thống CRM, hệ thống kiểm soát truy cập, nền tảng phân tích hoặc các công cụ nội bộ khác. Octo cho bạn biết những gì đã xảy ra với một hồ sơ, và bạn quyết định cách xử lý, lưu trữ và sử dụng dữ liệu đó.
Nếu bạn có một trường hợp sử dụng thực tế cho tính năng này, hãy chia sẻ với chúng tôi! Nhiều sự kiện hiện có ngày hôm nay đã được thêm vào nhằm phản hồi trực tiếp các tác vụ thực tế từ các nhóm đang làm việc với API.
Cập nhật với các tin tức Octo Browser mới nhất
Khi nhấp vào nút này, bạn sẽ đồng ý với Chính sách Quyền riêng tư của chúng tôi.
Cập nhật với các tin tức Octo Browser mới nhất
Khi nhấp vào nút này, bạn sẽ đồng ý với Chính sách Quyền riêng tư của chúng tôi.
Cập nhật với các tin tức Octo Browser mới nhất
Khi nhấp vào nút này, bạn sẽ đồng ý với Chính sách Quyền riêng tư của chúng tôi.

Tham gia Octo Browser ngay
Hoặc liên hệ với Dịch vụ khách hàng bất kì lúc nào nếu bạn có bất cứ thắc mắc nào.

Tham gia Octo Browser ngay
Hoặc liên hệ với Dịch vụ khách hàng bất kì lúc nào nếu bạn có bất cứ thắc mắc nào.
Tham gia Octo Browser ngay
Hoặc liên hệ với Dịch vụ khách hàng bất kì lúc nào nếu bạn có bất cứ thắc mắc nào.
