Bỏ qua, đến nội dung

Tracking ​

Kiểm các event Amplitude mà bản QA của app gửi khi chạy flow: khai báo event trong flow, xem kết quả ngay tại dòng.

Tracking kiểm các event Amplitude mà app gửi trong lúc chạy flow, như "Sign In Completed": event nào đã gửi, thiếu event nào, property nào sai. Kết quả có ngay khi flow chạy xong, không phải đợi dữ liệu lên Amplitude.

Các cách kiểm tra tracking

Chưa biết bắt đầu từ đâu? Xem Tracking: bắt đầu từ đâu.

Hai file làm việc cùng nhau:

FileChứa
FlowMỗi thao tác phải gửi event nào: các step assertEvents ngay dưới thao tác, và header tracking
Catalog (tracking-specs/<app>.yaml)Các rule cho mọi run: event, property, giá trị cho phép và rule chung. Xem Catalog tracking

Cho bản QA gửi event về Astra Scout ​

Astra Scout chỉ kiểm được event mà nó nhận được. Bình thường app gửi event lên Amplitude; bản QA phải gửi về Astra Scout trên máy Mac đang chạy flow.

Dev app cấu hình bản QA theo Gửi event của bản QA về Astra Scout. Với từng nền tảng:

  • iOS: bản QA đọc scoutServerUrl, địa chỉ mà Astra Scout tự đưa vào mỗi lần flow mở app, rồi dùng nó làm serverUrl (địa chỉ Amplitude SDK gửi event tới). Một bản QA dùng được cho mọi tester, cả simulator lẫn iOS device.
  • Android: bản QA đặt sẵn một serverUrl cố định, vì Astra Scout chưa đưa địa chỉ vào app Android.
  • Bản phát hành (production): không gửi về Astra Scout được. Tester chỉ tra cứu được sau khi test, xem Kết quả từ Amplitude.

Lấy địa chỉ để đặt cố định ​

Dùng khi bản QA không đọc scoutServerUrl (ví dụ bản Android). Astra Scout liệt kê sẵn các địa chỉ:

  1. Mở cửa sổ Tracking: Window → Tracking (Shift+Cmd+T).
  2. Bấm nút Hành động (biểu tượng …) trên thanh công cụ.
  3. Trong nhóm Sao chép địa chỉ cho bản QA, bấm nơi app chạy: iOS Simulator, Android Emulator, Device Android qua USB (adb reverse) hoặc Device cùng Wi-Fi. Địa chỉ được sao chép. Dòng đầu cho biết Astra Scout đã nhận bao nhiêu event.

Cửa sổ Tracking trước run đầu tiên

App chạy ở đâuĐịa chỉ
iOS Simulator trên cùng máy Machttp://127.0.0.1:5051/2/httpapi
Android emulatorhttp://10.0.2.2:5051/2/httpapi
Android device cắm USBhttp://127.0.0.1:5051/2/httpapi, sau khi chạy adb reverse tcp:5051 tcp:5051
iOS device hoặc Android device qua Wi-Fihttp://<tên máy Mac>.local:5051/2/httpapi. Máy và Mac phải chung Wi-Fi, và Nhận event từ device trong mạng trong Cài đặt → Amplitude phải bật (mặc định đã bật)

Bản QA nên gửi từng event ngay (flushQueueSize: 1, flushIntervalMillis: 1000), để event hiện ra khi bước đã gửi nó còn đang trên màn hình. Chỉ đặt serverUrl này trong bản QA, không bao giờ trong bản phát hành.

Một bản QA cho mọi máy Mac (iOS) ​

Mỗi lần flow chạy launchApp trên iOS, Astra Scout đưa vào app một launch argument tên scoutServerUrl. Giá trị là địa chỉ của chính máy Mac đang chạy flow, kèm một mã riêng của device. iOS tự đặt giá trị này vào UserDefaults, nên bản QA chỉ cần đọc ra:

swift
// Chỉ bản QA: ưu tiên địa chỉ Astra Scout đưa vào lúc mở app.
if let scout = UserDefaults.standard.string(forKey: "scoutServerUrl"), !scout.isEmpty {
    serverUrl = scout
}

Kết quả:

  • Một bản build dùng được cho mọi tester và mọi máy Mac.
  • Simulator và iOS device trên cùng máy Mac nhận địa chỉ khác nhau, mỗi cái đúng với cách device đó tìm tới Mac.
  • Event của device nào chỉ vào run của device đó, điện thoại khác trong cùng mạng không lẫn vào.

Flow tự ghi scoutServerUrl trong launchApp: arguments: thì Astra Scout giữ giá trị của flow. Cấu hình Xcode và dạng đầy đủ của địa chỉ: Gửi event của bản QA về Astra Scout.

Event gửi tới địa chỉ chung (không có mã device, ví dụ http://127.0.0.1:5051/2/httpapi) vẫn được gắn vào run đang chạy, chỉ là không tách được theo device.

Tắt nhận event từ mạng khi dùng mạng không tin cậy

Astra Scout chỉ nhận event, nhưng máy khác trong cùng mạng cũng gửi vào được. Trên mạng công cộng, tắt Nhận event từ device trong mạng trong Cài đặt → Amplitude; simulator vẫn chạy bình thường. Công tắc có hiệu lực sau khi bấm Khởi động lại server ngay.

Kiểm một run ​

  1. Mở một workspace. Astra Scout tìm catalog trong tracking-specs/ của workspace và tối đa ba thư mục cha. Mỗi app có một catalog, ví dụ tracking-specs/mydmv.yaml. Tab và cửa sổ Tracking ghi "Không có spec nào trong tracking-specs/ (đã tìm trong workspace và các thư mục cha)." khi không tìm thấy.

  2. Chạy flow bằng Chạy test (Cmd+R) hoặc Chạy tất cả test (Shift+Cmd+R).

  3. Trong thanh runner dưới editor, bấm Tracking (cạnh Step). Tab tóm tắt run mới nhất: kết luận, "Kiểm tra trong flow: N/M pass", issue đầu tiên ("Còn N issue trong cửa sổ Tracking" khi còn nữa) và các API key mà event mang theo.

    Tab Tracking của runner sau một run

  4. Bấm vào issue, hoặc Mở cửa sổ Tracking…, để xem cả run.

Nếu không có gì đến, tab cho bạn biết vì sao. "App chưa gửi API key nào qua Astra Scout (serverUrl của app đã trỏ về Scout chưa?)" cho biết bản build không gửi tới Scout: kiểm tra serverUrl. "Ghi Amplitude: …" cho biết listener không khởi động được.

Cửa sổ Tracking (Window → Tracking, Shift+Cmd+T) hiện một run mỗi lần và theo run mới nhất cho đến khi bạn chọn run khác. Cửa sổ không tự mở.

Cửa sổ Tracking: các event của một run cùng check và issue

PhầnHiện
Thanh bênMục Test run: mỗi run đã ghi, kèm flow, nền tảng, số event và dấu pass, warning hoặc fail ("Chưa bắt được run nào" khi trống). Mục Ngoài run: hàng Event ngoài run kèm số đếm
Event streamCác event của run theo thời gian, xen các step của flow (launchApp, tapOn…) để thấy step nào gửi event nào. Step assertEvents hiện kết quả. Run do agent khởi động qua MCP hoặc qua API cũng hiện các step, ngay khi chúng chạy. Mỗi event hiện issue của nó (nếu có); khoảng nghỉ từ một giây trở lên hiện thành khoảng trống
Thanh kiểm traKhi chưa chọn event: kết luận (biểu tượng trạng thái, Pass, Warning hoặc Fail, và "N error · N warning · N event · nền tảng"), dòng Catalog, Kiểm tra trong flow, các Issue (ẩn khi trống; bấm một mục để xem event của nó), mục Amplitude, mục Event từ server, user property cuối run và các Rule. Khi chọn một event: property của nó, các user property nó đặt, và toàn bộ user property tại event đó. Nút Hiện issue ở đầu màn đó quay lại các issue của run

Thanh dưới stream có các điều khiển sau:

Điều khiểnLàm gì
Hiện step của flowHiện các step của flow xen giữa các event. Mặc định bật; Scout nhớ lựa chọn
Ẩn event SDKGộp $identify và các event [Amplitude] …, trừ khi kiểm tra đánh dấu một event. Mặc định bật, nên event [Amplitude] … trông như thiếu cho đến khi bạn tắt; Scout nhớ lựa chọn
Chỉ hiện mục có issueChỉ giữ các event có issue
NhómMenu hiện khi event của catalog có nhóm: Mọi nhóm, một nhóm, hoặc Không có nhóm, gồm các event mà catalog không liệt kê
Lọc eventÔ lọc theo chữ

Biểu tượng trước tên event cho biết nguồn gửi: chữ A màu xanh cho Amplitude SDK ([Amplitude] Application Opened hiện là "Application Opened"), bình thí nghiệm màu tím cho Amplitude Experiment ([Experiment] Assignment, $exposure), hình người màu xám cho $identify; event riêng của app không có biểu tượng. Tắt Ẩn event SDK để thấy chúng.

Thanh công cụ của cửa sổ có:

  • Hành động (nút …): Kiểm tra lại, Xuất JSON…, Nền tảng (Tự động đọc từ event), các mục Sao chép địa chỉ cho bản QA và Xoá các run đã ghi.
  • So sánh iOS ↔ Android…, xem bên dưới.
  • Ẩn thanh kiểm tra / Hiện thanh kiểm tra, và nút trợ giúp mở Tracking: bắt đầu từ đâu.

Khai báo kiểm tra trong flow ​

Đặt phần kiểm ngay dưới thao tác gửi event. Flow cũng nêu catalog của nó trong header tracking trước dấu ---:

yaml
appId: ${APP_ID}
tracking:
  spec: mydmv                  # tracking-specs/mydmv.yaml; optional when the workspace has one catalog
  forbid: [Purchase Initiated, Purchase Completed, Purchase Failed]   # events the whole run must not send
---
- tapOn: "Car"
- tapOn: "Continue"
- assertEvents:
    - License Selected:
        license type: car
        placement: onboarding
Key headerÝ nghĩa
specCatalog, viết là tên không có đuôi hoặc đường dẫn tương đối
forbidCác event run không được gửi, ở bất kỳ step nào

Chỉ header của flow cấp cao nhất được tính. Key không hợp lệ dưới tracking, hoặc spec không tìm ra file, làm flow không hợp lệ. Dòng Catalog trong thanh kiểm tra của cửa sổ Tracking cho biết run được kiểm tra theo catalog nào. Khi workspace có nhiều catalog, dòng này là một menu: mặc định là Catalog của flow, và catalog chọn ở đó áp dụng cho file flow đó.

Ba cách viết ​

yaml
- assertEvents: [Onboarding Step Viewed, Profile Created]   # names only
- assertEvents:                                             # names with values
    - License Selected:
        license type: car
    - Paywall Viewed: { placement: onboarding }
- assertEvents:                                             # with a timeout
    timeout: 8000
    events:
      - Paywall Viewed: { placement: onboarding }

Giá trị property là giá trị thường, phải bằng đúng cái app đã gửi, hoặc một map điều kiện (in, min, max, regex, type). Ngày (date: 2026-10-19) được so đúng như chữ đã viết. Danh sách đầy đủ nằm ở tham chiếu assertEvents.

Một lần kiểm hoạt động thế nào ​

  • Cửa sổ thời gian. Lần kiểm xét các event từ 500 ms trước thao tác cuối cùng đụng tới app (chạm, gõ, vuốt, launchApp). Lệnh chờ và lệnh assert không làm nó dịch chuyển. Vậy tapOn rồi assertEvents sẽ kiểm event của lần chạm đó. Thời gian tính theo đồng hồ của Mac, nên đồng hồ thiết bị lệch cũng không sao.
  • Timeout. Step chờ tối đa timeout mili giây (mặc định 5000) cho event chưa đến. Thời gian chờ tính từ chính step assertEvents.
  • Mỗi event một lần. Mỗi event được liệt kê phải khớp một event app đã gửi. Event mà một assertEvents đã khớp thì assertEvents sau không dùng lại. Thứ tự trong cùng một step không quan trọng.
  • Sau một block. assertEvents ngay sau runFlow hoặc repeat kiểm mọi event block đó đã gửi.
  • Nhánh. assertEvents trong runFlow có when chỉ được kiểm khi nhánh đó chạy. Dòng chưa từng chạy thì không có kết quả.
  • Fail không dừng flow. Event thiếu hoặc sai giá trị làm step fail và nói rõ vì sao; các lệnh tiếp theo vẫn chạy, và run kết thúc ở trạng thái fail.
  • forbid. Bất kỳ event nào trong danh sách, ở bất kỳ lúc nào, làm lần kiểm flow:forbidden fail.
  • Mọi event còn được kiểm theo catalog, dù có nêu trong flow hay không: tên chưa có trong catalog, kiểu sai, thiếu property bắt buộc, rule chung.

Event SDK như $identify và [Amplitude] … bị assertEvents bỏ qua.

Gõ trong editor ​

Viết tên event trong catalog (tên Display) vào assertEvents, forbid và rule. Gán event vào flow… cũng ghi tên trong catalog.

Để tự viết một check:

  1. Mở file flow và đặt con trỏ ở dòng mới ngay dưới thao tác gửi event.
  2. Gõ - assertEvents:. Bên trong step, editor gợi ý tên event từ catalog của flow.
  3. Chọn một tên. Editor tiếp tục gợi ý property của event đó (property bắt buộc lên đầu), rồi giá trị cho phép của property. Chọn một tên có property bắt buộc thì mỗi property được thêm một dòng.
  4. Chạy flow và đọc kết quả ở dòng đó, xem bên dưới.

Editor gợi ý tên event, rồi property, bên trong assertEvents

Kết quả trong editor ​

Sau khi chạy, editor hiện kết quả của từng assertEvents ngay chỗ bạn viết. Kết quả chỉ hiện khi file chưa đổi kể từ lúc chạy; sửa file thì kết quả ẩn đến run sau.

Kết quả assertEvents ngay tại dòng trong editor

Ở đâuHiện
Số dòng✓ pass, ✕ fail, ▲ warning (step optional hoặc bị ngắt). Dòng chạy nhiều lần hiện kết quả xấu nhất
Cuối dòng failMột banner ngắn có thông báo, ví dụ event nào không bao giờ đến
Bảng runDưới mỗi step assertEvents, một hàng cho mỗi event mong đợi: đã khớp kèm thời gian, hoặc issue (ảnh bên dưới)
Danh sách Kiểm tra trong flowTrong tab Tracking và cửa sổ Tracking: một hàng cho mỗi run của một dòng assertEvents. Mũi tên (Xem trong flow, cũng có trong menu chuột phải của hàng) mở file ở dòng đó

Các step của runner: mỗi step assertEvents có một hàng cho mỗi event mong đợi

Bấm dấu ✓ ✕ ▲ hoặc banner để mở tab Event trong thanh kiểm tra. Tab Event là biểu tượng danh sách của nút chuyển ở đầu thanh kiểm tra (nút kia là Device). Nút chuyển chỉ hiện khi con trỏ nằm trong một step assertEvents hoặc trên một dòng thao tác. Tab không tự mở khi bạn di con trỏ.

Tab Event của một dòng assertEvents

Tab Event có các mục sau, từ trên xuống:

MụcHiện
Một mục cho mỗi event mong đợi, đặt tên theo eventCác giá trị bạn đã viết, một hàng cho mỗi property. Chọn giá trị cho phép từ menu, tick boolean, gõ giá trị khác, thêm hoặc xoá property. Mọi sửa đổi đi qua văn bản nên ⌘Z hoàn tác được. Điều kiện như { in: [1, 2] } chỉ đọc ở đây: sửa trong văn bản
TimeoutTimeout của step, tính bằng mili giây. Để trống là mặc định, 5000 ms
Các rule được kiểm tra tự độngCác rule của catalog áp dụng cho những event này, viết thành câu thường, mỗi rule có Mở trong catalog. Event mà catalog chưa có thì được nêu rõ
Run mới nhấtKết quả, thời gian, timeout, phần khớp hoặc issue của từng event mong đợi, và các event nhận được trong cửa sổ cùng property của chúng
Cách sửa (dòng fail)Các cách sửa nhanh, bên dưới

Cách sửa nhanh ​

NútLàm gì
Đổi tên trong flowMenu các tên event app đã gửi, gần nhất lên đầu. Chọn một tên sẽ viết lại tên trong flow. Khi có nhiều event fail, mỗi event một menu "Đổi tên <event> trong flow"
Thêm vào catalogMenu các event mà catalog chưa có. Chọn một event mở alert "Ghi event này vào catalog?" nêu tên event và file catalog, kèm Thêm và Huỷ
Báo bug lên Jira…Mở báo cáo Jira với error của dòng này đã chọn sẵn

Gán event từ một run ​

Scout có thể viết các check assertEvents từ những gì app đã gửi trong một run.

  1. Chạy flow một lần. Phải thiết lập xong phần ghi event (xem ở trên).

  2. Đọc thanh thông tin. Khi run mới nhất của flow đang mở có event mà flow chưa kiểm, một thanh xanh hiện trên editor: "Run 14:02 nhận 31 event, 12 event chưa có trong flow." Khi có event sai rule, thanh thêm "Vi phạm rule: N.". Ẩn lần này đóng thanh cho run đó.

    Editor sau một run: thanh thông tin và các số màu xám ở dòng thao tác

  3. Xem các số màu xám. Mỗi dòng thao tác có ◉ N, số event app đã gửi sau thao tác đó. Dòng có con trỏ nói rõ hơn. Muốn ghi riêng một event, bấm vào số (hoặc bấm chuột phải dòng thao tác và chọn Thêm kiểm event…). Tab Event liệt kê các event đó. Thêm tên event ghi tên, Thêm kèm giá trị ghi tên cùng giá trị app đã gửi.

    Tab Event của một dòng thao tác

  4. Mở sheet. Muốn ghi nhiều event cùng lúc, bấm Gán event vào flow… trên thanh thông tin. Sheet "Gán event vào flow từ run" mở ra. Mỗi event được xếp dưới thao tác chạy ngay trước nó.

  5. Tick và ghi. Chọn các event muốn kiểm và bấm Ghi vào flow.

Sheet Gán event vào flow từ run

Sheet hoạt động như sau:

  • Run của flow này chọn bất kỳ run nào của file này.

  • Event đúng rule của catalog, và event catalog chưa có (kèm warning), được tick sẵn. Event sai rule thì không tick. Menu … cạnh ô tìm kiếm có Chọn mọi event đúng rule và Bỏ chọn hết để đổi nhiều mục cùng lúc.

  • Ghi giá trị là Giá trị giống nhau ở mọi run hoặc Chỉ tên event. Với lựa chọn đầu, Scout chỉ ghi các giá trị giữ nguyên qua các run và bỏ id, giờ, ngày, đánh dấu "không ghi".

  • Event SDK ($identify, [Amplitude] …) bị bỏ ra và không có ô tick.

  • Sai thao tác. Nếu Scout đoán sai thao tác, Thao tác chuyển event sang thao tác khác.

  • Event đến trễ. Event đến sau thao tác hơn 5 s được ghi timeout dài hơn, và hàng đó cho biết.

  • Cuối flow. Event gửi sau khi flow kết thúc nằm dưới Sau khi flow kết thúc. Chúng không có ô tick và không được ghi: không step nào trong flow kiểm được chúng.

  • Subflow. Thao tác trong subflow runFlow: file: được assertEvents ngay sau dòng runFlow trong flow đang mở. File subflow không bị đổi. Thao tác trong runFlow có when được assertEvents bên trong nhánh đó.

  • Mở Xem trước rồi chuyển giữa Event đang chọn và Toàn bộ thay đổi để xem các dòng trước khi ghi.

    Phần xem trước các dòng sheet sẽ ghi

  • Chạy lại flow sau khi ghi để kiểm chạy flow lần nữa.

Scout ghi vào văn bản editor đang mở, thành một thay đổi: ⌘Z hoàn tác cả lần gán, còn comment và các dòng khác không bị đụng tới. Nếu một dòng thao tác đã đổi kể từ run, event của nó hiện "dòng đã đổi, chạy lại flow".

Một run được kiểm theo gì ​

Check idĐến từÁp dụng khi
schema:*, global:*Catalog: events, enums, user_properties, global_rulesLuôn luôn, với mọi event của run
cross:*cross_checks trong catalogLuôn luôn. N/A khi các event cần so sánh không có trong run
assert:<file>:<line>Một cái cho mỗi dòng assertEvents. Fail khi bất kỳ run nào của dòng fail. Step optional fail chỉ là warningDòng đó đã chạy. Dòng chưa chạy thì không có hàng
flow:forbiddentracking.forbid trong header của flowHeader có mục tracking. N/A khi forbid trống
userprop:<property>@<event>user_property_rules.rules trong catalogEvent kích hoạt (after) có trong run. N/A nếu không có
identity:*identity trong catalogĐịnh dạng device_id và user_id: luôn luôn. Rule đăng nhập: có event đăng nhập trong run. Rule đăng xuất: có event đăng xuất trong run
server:<id>server_checks trong catalogEvent after có trong run. N/A nếu không có
amplitude:*Đọc lại từ AmplitudeXem Kết quả từ Amplitude

Rule không áp dụng là N/A, không phải pass. Run mà mọi rule đều N/A thì cả run là N/A.

Danh sách Kiểm tra trong flow có một hàng cho mỗi lần thực thi assertEvents: trạng thái, tên event, lý do khi fail, và "dòng N". Bấm một hàng sẽ chọn event của nó trong stream. assertEvents fail không lặp lại trong Issue, vì hàng ở đây đã hiện nó.

Khi run còn đang diễn ra, assertEvents còn đang chờ, một user property được đặt hoặc giá trị cuối chưa đến sẽ hiện Đang chờ thay vì fail, và kết quả là Đang chờ cho đến khi run kết thúc hoặc một rule fail. Event hoặc property sai thì fail ngay.

Rule có severity error làm lần kiểm fail; warn chỉ ghi nhận. Event đến ngoài mọi run nằm dưới Event ngoài mọi run. Dùng Xuất JSON… để đính kèm spec, report và event vào ticket, và Xoá các run đã ghi để đặt lại (cả hai nằm trong menu Hành động).

Để đổi rule, xem Catalog tracking. Các phần dưới đây nói về những kiểm tra nằm trong catalog nhưng cần nhiều hơn một rule property.

Rule cho user property ​

Catalog cũng kiểm được các user property mà app đặt (các op Identify của Amplitude như $set, $setOnce, $add, $unset). Thêm mục user_property_rules. Mỗi rule cần một event after: rule chỉ chạy khi event đó có trong run, nếu không là N/A.

yaml
user_property_rules:
  severity: warn                 # default for the rules below
  forbid_ops: ["$clearAll"]      # ops that must not appear
  rules:
    - property: access level
      op: "$set"                 # $set, $setOnce, $add, $unset, $append, $prepend, $preInsert, $postInsert, $remove or any
      after: { event: Purchase Completed, within_ms: 10000 }
      value: { in: [trial, premium] }
      final: { equals: premium } # value after applying every op of the run
    - property: first open date
      op: "$setOnce"
      after: { event: Onboarding Started }
      set_once_stable: true      # never overwritten by $set, $unset or $clearAll in the run
      amplitude: final           # also check the value stored in Amplitude
    - property: onboarding paywall status
      op: "$set"
      after: { event: Paywall Skipped, where: { placement: onboarding } }   # same conditions as assertEvents
      value: { equals: skipped }
      persist: true              # still stored after a new session
KeyÝ nghĩa
property, opProperty và phép toán cần tìm (op mặc định là any)
valueRàng buộc cho giá trị của mỗi op khớp, giống property của event, thêm type, regex, max và from_prop
afterBắt buộc. Event kích hoạt rule; where giới hạn cho event có các giá trị property này. Op phải đến trong vòng within_ms (mặc định 10000) sau event đã nêu, hoặc tối đa before_ms (mặc định 1000, -1 là tắt) trước nó: app thường identify ngay trước event mà nó đặt property cho
countCó bao nhiêu op khớp (mặc định ít nhất 1)
finalRàng buộc cho giá trị sau khi gộp mọi op của run
forbid_opsCác op không được xuất hiện, như $clearAll
set_once_stableProperty $setOnce không bị op khác đổi trong run
persistProperty còn lại sang session mới (kiểm trên Amplitude)
severityerror hoặc warn cho rule đó. Rule chỉ kiểm trên payload đã bắt mặc định là error, rule cần Amplitude mặc định là warn

Mỗi rule có id userprop:<property>@<event>. Rule đánh dấu needs_confirmation: true vẫn là warning cho đến khi team xác nhận.

Catalog user property ​

Thêm user_properties ở đầu spec (cạnh events) để kiểm mọi giá trị app đặt, giống property của event: type, enum hoặc enum_ref, regex, min, not_empty, forbidden. User property mà catalog không liệt kê sẽ theo global_rules.unknown_user_properties (ignore, warn là mặc định, hoặc error). Mỗi property và mỗi giá trị chỉ được báo một lần, vì SDK lặp lại $setOnce ở mọi event.

yaml
user_properties:
  days until exam: { type: integer }
  access level: { type: string, enum_ref: access level }
global_rules:
  unknown_user_properties: { severity: warn }

Lựa chọn tương tự có cho từng event với property của event: extra_properties: ignore | warn | error trên event (mặc định là global_rules.unknown_properties). Khi property có required: true, ignore yêu cầu "những property này phải có, còn lại không quan trọng"; error yêu cầu "đúng những property này, không hơn".

Đăng nhập và profile Amplitude ​

Mục identity của catalog kiểm user_id và device_id quanh lúc đăng nhập, và xem Amplitude có gộp profile ẩn danh vào profile của user không:

yaml
identity:
  login_event: [Sign In Completed, Signup Completed]   # a name or a list
  device_id: stable              # or reset_on_logout (needs logout_event)
  user_id: { regex: "^[0-9a-f]{24}$" }
  amplitude_merge: true          # default when login_event is set

Kiểm tra định dạng device_id và user_id luôn chạy. Kiểm tra đăng nhập chạy khi có event đăng nhập trong run, và kiểm tra đăng xuất chạy khi có event đăng xuất. Gộp lại, chúng kiểm rằng không event nào mang user_id trước login_event, event sau đó thì có (châm chước 2 event hoặc 10 s), user_id không đổi nếu không đăng xuất và đúng định dạng, và với logout_event thì nó biến mất sau khi đăng xuất. amplitude_merge đọc lại user từ Amplitude và báo warning khi device_id mà app có trước lúc đăng nhập không nằm trong profile của user đó: Amplitude giữ hai profile cho một người.

Kết nối Amplitude ​

Ghi event không cần tài khoản Amplitude. Để kiểm thêm cái Amplitude thực sự đã lưu, thêm project của bạn trong Cài đặt → Amplitude (Thêm project…):

Cài đặt → Amplitude với một project

  1. Trong Amplitude, mở Settings → Projects → project của bạn → General và sao chép API Key và Secret Key.

  2. Trong Astra Scout, mở Cài đặt → Amplitude và bấm Thêm project…. Form thêm mở ra. Điền tên và cả hai key. Vùng mặc định là Tự động: form ghi "Khi lưu, app thử vùng US rồi EU." Bạn vẫn có thể tự chọn US hoặc EU. Bấm Lưu.

  3. Trên hàng của project, Kiểm tra kết nối kiểm tra các key. Hàng còn có Sửa… và Xoá project.

    Form project: tên, key, vùng, ID project Amplitude, chuyển tiếp và key của app

  4. Đặt Chuyển tiếp event tới Amplitude, trên hàng của project hoặc trong form. Mục này tắt sẵn cho từng project. Khi bật, một hộp thoại hỏi bạn xác nhận. Chỉ bật khi project dùng cho Staging: event ghi được trong run cũng được gửi tới Amplitude để đọc lại. Giữ tắt cho Production: dữ liệu test không được đi vào đó. Với Production, dùng tra cứu chỉ đọc.

  5. Có thể điền ID project Amplitude (chỉ chữ số, ví dụ 123456, lấy từ Settings → Projects trong Amplitude). Scout không đọc được nó từ key. Nếu Amplitude báo một project cho run, form gợi ý Amplitude báo project N, dùng ID này?. Form không bao giờ tự điền ô này.

Mỗi run dùng project có API key mà app đã gửi, nên bạn không phải chọn project cho từng run.

Một project Amplitude có thể có nhiều API key (Organization settings → API Keys liệt kê theo project). Khi các bản build của app gửi bằng key khác key bạn đã đưa cho Scout, ví dụ key legacy của project, thêm nó vào Key của app trong cùng form project (hàng của project liệt kê chúng dạng "Key của app ••••8ebb"). Chỉ cần key, không cần Secret key. Run gửi bằng API key hoặc bất kỳ key của app nào thuộc về project đó; Scout vẫn đọc Amplitude bằng API key và Secret key. Form chỉ hiện key của app bằng 4 ký tự cuối.

Sai project Amplitude ​

Khi spec nêu project của nó (source.amplitude_project_id) và ID project đã đặt trong Cài đặt → Amplitude, Scout so hai giá trị cho mỗi API key app đã gửi. Không khớp là rule amplitude_wrong_project với severity error: thông báo nêu cả hai ID project và không bao giờ nêu key. Việc kiểm chạy cục bộ, không cần mạng. Kết quả là na, kèm lý do, khi spec không có source.amplitude_project_id, run không gửi API key nào qua Scout, key không có trong Cài đặt → Amplitude, hoặc project đó chưa có ID project.

Kết quả từ Amplitude ​

Mục Amplitude nêu từng API key run đã gửi bằng 4 ký tự cuối và project nó khớp trong Cài đặt → Amplitude (theo API key hoặc key của app), hoặc báo key chưa có ở đó, kèm Mở cài đặt Amplitude…. Dưới các key là các hàng Đã chuyển tiếp ("N đã gửi · N fail · N bỏ qua"), Trạng thái và User, cùng hai nút Tra cứu người dùng… và Kiểm tra trên Amplitude ở cuối mục. Trạng thái ghi "Đang chờ Amplitude · lần thử N · lần kiểm tra tiếp theo sau N giây" khi Scout đang poll, rồi "Đã đọc từ Amplitude · N event".

Mục Amplitude của thanh kiểm tra

Danh sách Rule hiện trước các rule fail, warning hoặc đang chờ. Các rule pass được gộp dưới "Cả N rule đều pass".

Sau run Staging, Scout đọc lại test user từ Amplitude và điền kết quả cho các rule dùng amplitude, persist và set_once_stable. Amplitude có thể mất một lúc để ingest event, nên Scout poll tối đa khoảng 2 phút. Các rule này hiện trong cửa sổ Tracking cạnh các rule khác, và trong report. Kiểm tra trên Amplitude đọc lại run lần nữa.

Kết quảÝ nghĩa
naChưa kiểm: key chưa có project Amplitude nào được cấu hình, việc đọc lại chưa xong, hoặc không có gì để so sánh
amplitude_unavailable (warn)Không đọc được Amplitude (sai key, rate limit hoặc timeout). Không bao giờ tính là pass

Với run không được chuyển tiếp (Production), tra một tài khoản test bằng tay:

  1. Trong cửa sổ Tracking, mở mục Amplitude của thanh kiểm tra và bấm Tra cứu người dùng….
  2. Điền User ID, hoặc Device ID (một trong hai là đủ), và chọn Project. Danh sách trống cho đến khi bạn thêm project trong Cài đặt → Amplitude.
  3. Bấm Kiểm tra trên Amplitude. Scout chỉ đọc các property đã lưu và các event mới nhất rồi kiểm theo spec. Không có gì được gửi tới Amplitude.

MCP tool amplitude_user_lookup làm điều tương tự từ terminal.

Event từ server ​

Một số event do backend gửi, không phải app (ví dụ Trial Started sau khi Apple hoặc Google xác nhận giao dịch). Thêm danh sách server_checks vào catalog. Mỗi check bắt đầu từ một event after: khi event đó có trong run, Scout tìm event của backend trên Amplitude sau run.

yaml
server_checks:
  - id: trial_started          # optional; the default is the after event. Ids are unique
    after: { event: Purchase Completed }
    wait_minutes: 15           # default 15, at most 60
    severity: warn             # default warn
    expect_one_of: [Trial Started, Subscription Started]
    props:
      $revenue: { type: number, min: 0 }
KeyÝ nghĩa
idTên của check; hàng của nó là server:<id>
afterEvent trong run kích hoạt check. Không có nó trong run thì check là N/A
wait_minutesEvent được phép mất bao lâu để xuất hiện (mặc định 15, từ 1 đến 60)
severityerror hoặc warn nếu event thiếu hoặc sai (mặc định warn)
expect_one_ofTên event. Một trong số đó phải xuất hiện cho test user, sau event kích hoạt
propsRàng buộc cho property của event đó, giống property của event

Event từ backend được tra theo user_id. Khi event app gửi trong run không có user_id (tester chưa đăng nhập), Scout dùng user mà Amplitude đã gắn với device của run; kết quả ghi rõ user_id đã dùng. Event app gửi trong run không bao giờ được tính (so theo insert_id); event từ backend có thể mang device_id của app.

Scout đọc các event mới nhất của test user ở phút thứ 1, 2, 4 và 8 sau run, rồi cứ 8 phút một lần cho đến hết wait_minutes. Mọi check của một run dùng chung một vòng poll; mỗi check có thời gian chờ và kết quả riêng. Mỗi lần tra cứu tính vào rate limit của Amplitude, mà Scout dùng chung cho mỗi project (4 request một phút), nên một check mặc định tốn khoảng 4 request. Khi bị rate limit, Scout chờ rồi thử lại. Các hàng hiện dưới Event từ server trong thanh kiểm tra của cửa sổ Tracking:

Kết quảÝ nghĩa
Đang chờVẫn đang tìm: Scout hiện lần thử thứ mấy và khi nào kiểm tiếp
passCó event khớp đến và property đúng
fail hoặc warnKhông có event khớp trong wait_minutes (theo severity của spec). Thông báo liệt kê các event khác Amplitude có sau event kích hoạt, để biết backend đã gửi gì thay vào
naChưa kiểm, kèm lý do: event kích hoạt không có trong run, run không có user_id hoặc device_id nào biết được, chưa cấu hình project Amplitude, hoặc việc đọc lại bị ngắt
amplitude_unavailable (warn)Không đọc được Amplitude (sai key hoặc bị từ chối truy cập). Không bao giờ tính là pass

Kết quả chỉ giữ trong bộ nhớ, giống các run. Sau khi server Studio khởi động lại, check đang chờ hiện na ("server check interrupted, re-run"): chạy lại.

So sánh iOS ↔ Android ​

Để xem hai app có gửi cùng tracking không, chạy cùng một file flow trên iOS và Android, rồi so sánh:

  1. Mở cửa sổ Tracking và bấm So sánh iOS ↔ Android… trên thanh công cụ. Nút tắt khi workspace chưa có catalog hợp lệ.
  2. Trong sheet, chọn Flow. Danh sách chỉ có flow có run trên cả hai nền tảng ("Chưa có flow nào có run trên cả hai nền tảng" khi không có). Sheet chỉ liệt kê các run của file đó.
  3. Chọn một Run iOS và một Run Android. Run đã xong mới nhất của mỗi bên được chọn sẵn. Run của các file flow khác nhau bị từ chối.
  4. Bấm So sánh. Sheet hiện kết quả. Bấm Xong để đóng.

Kết quả So sánh iOS ↔ Android…

Các tab Thứ tự, Events và User property hiện mỗi hàng là Giống nhau, Khác nhau, Chỉ có trên iOS hoặc Chỉ có trên Android. Bật Chỉ khác biệt (cạnh các tab) để ẩn các hàng giống nhau. Scout không so giá trị: chỉ so thứ tự event, tên property và kiểu của chúng (string, number, boolean, list, object). Kết quả chỉ để tham khảo: nó không thêm finding nào vào lần kiểm hay report.

Các mục chỉ có trên một nền tảng có thể bỏ qua trong catalog:

yaml
parity:
  ignore_events: [Notification Permission Requested]
  ignore_props: [haptics enabled]   # also applies to user properties

Event nội bộ của SDK ([Amplitude] …) luôn bị bỏ ra.

Quyền riêng tư ​

API key và Secret key được lưu mã hoá trên Mac của bạn. Chúng không bao giờ xuất hiện trong report, log, bản xuất hay output MCP. Lịch sử Scout giữ trên đĩa để so sánh các run chỉ nhận diện user bằng hash, và các mục cũ được dọn tự động.

Từ terminal ​

MCP tool check_tracking (skill check-tracking của plugin) kiểm event của một run theo spec nêu trong header của flow. specPath là không bắt buộc; kết quả là spec_not_found khi không tìm ra catalog nào. Report liệt kê header flow và một hàng cho mỗi dòng assertEvents. Nó cũng gồm các hàng event từ server, có thể còn đang chờ ngay sau run: gọi lại sau. compare_tracking_runs làm cùng phép so sánh như So sánh iOS ↔ Android… (không bắt buộc flowPath, specPath, iosFlowId, androidFlowId; mặc định là run đã xong mới nhất của mỗi nền tảng cùng file flow). Các tool tracking khác: read_tracking_spec, list_tracking_specs, suggest_tracking_spec, edit_tracking_spec, get_unassigned_events, get_tracking_coverage và import_taxonomy. Xem Plugin scout.