openvidu/openvidu-dashboard/dashboard-ce/tools/data-generator/README.md

9.6 KiB
Raw Blame History

Data generator

Fills a MongoDB database with analytics data that follows the data model contract of @openvidu-dashboard/typings: a deterministic scenario S, M or L over a number of days ending now. The backend integration tests use it for their query plan and latency checks, and ./dashboard.sh demo uses it for the local demo database.

Before inserting, src/schema.ts creates every collection, index and TTL of the contract and gives the plain collections the contract validator with validationAction: error, so a document that drifts from the contract fails the run (track_stats takes no validator as a time-series collection). src/contract.ts turns each model document into its stored shape: the model's bookkeeping removed, absent fields omitted and every number in the BSON type its schema declares.

The package is also a library for the backend integration tests (dashboard-ce/backend/test/): ./generator (generate(db, options)), ./context (queryContext(db): the data range and sample identifiers), ./plan (explain summaries used by the expectIndexBacked harness) and ./schema (createCollections()).

Requirements: the workspace installed (./dashboard.sh install), a reachable MongoDB (8.x; time-series collections are used when the server accepts them) and a user allowed to create and drop the target database. Run the commands from this directory.

Usage

pnpm generate --uri "$MONGO_URI" --db ov_data_s --scenario S --days 30 --drop
pnpm generate --uri "$MONGO_URI" --db ov_data_m --scenario M --days 7 --drop
pnpm generate --uri "$MONGO_URI" --db ov_data_l --scenario L --days 1 --drop --stats-mode track
Option Default Meaning
--uri, --db required Connection string and target database
--scenario S|M|L required Rooms per day, sessions per day and average room size (table below)
--days <n> required Days of history ending now
--stats-mode participant|track participant One track_stats document per participant and direction, or per track
--seed <n> 1 Seed of the pseudo-random generator (mulberry32); same seed, same data
--retention-events-days <n> 7 Only raw events inside this window are written (TTL index on ts)
--retention-stats-days <n> 7 Only stats inside this window are written (expireAfterSeconds)
--retention-tracks-days <n> 7 expiresAt of tracks and subscriptions; expired ones are not written
--retention-entities-days <n> 90 expiresAt = closedAt + retention on closed entities
--retention-rollups-5min-days <n> 7 Only 5-minute rollups inside this window are written (TTL index on bucket)
--drop off Drop the database first
--plain-stats off Force the plain-collection fallback for track_stats
--five-minute-rollups off Write analytics_5min inside the 5-minute rollup window
--node-rollups off Write the node:<nodeId> scope beside global in every rollup
--room-sums off Write rooms.participantsSum and rooms.durationMsSum at room end
--active-window <minutes> off Rooms created in the last minutes stay active (two of three); without it, the most recent 10 % of the rooms are active
--min-active-rooms <n> 0 With --active-window: rooms added to the window when the hour of day leaves fewer than n active rooms
Scenario Rooms per day Sessions per day Average room size
S 200 1 000 4
M 2 000 20 000 6
L 5 000 50 000 8

What it writes (analytics_5min stays empty without --five-minute-rollups):

  • rooms: created over the days with a diurnal curve (office-hours peak); the most recent 10 % are active, the rest closed with endReason and closedBy. Id arrays and counters (participantSids, activeParticipantSids, identities, participants.*, trackSids, egressIds, ingressSessionIds, features) are derived from the generated entities; participant counters count STANDARD sessions and byKind every kind, as the writer does (also in the rollups).
  • participants: unique identities per room follow a Poisson distribution around the scenario average; the difference between sessions/day and rooms/day × average size is produced as reconnects (DUPLICATE_IDENTITY leave plus a new session of the same identity). Sessions last ~20 min, 3 % are aborted, 95 % are STANDARD; rooms with egress/ingress/agent/SIP get the matching participant kinds. Client (sdk/os/browser/device/network), connection type, connect time, disconnect reason and resumes follow fixed distributions.
  • tracks (CAMERA video + MICROPHONE audio per publishing participant, with simulcast layers and final publish stats) and track_subscriptions (every participant subscribes to the tracks of the other identities present at the same time; 1 % failed).
  • egresses (10 % of rooms; mostly room_composite; complete/failed/aborted, active in active rooms), ingresses and ingress_sessions (2 % of rooms).
  • events: lifecycle events of rooms, participants, tracks, subscriptions, egresses and ingresses with small payloads, only inside the events retention window.
  • track_stats: one document per 30 s per participant and direction (participant mode) or per track and direction (track mode), only inside the stats retention window, with plausible score/bytes/rtt/jitter. Time-series collection (timeField: ts, metaField: meta, granularity: seconds) with expireAfterSeconds; plain collection with a TTL index on ts when the server rejects time-series.
  • analytics_hourly and analytics_daily (global scope, plus one scope per node with --node-rollups) aggregated from the generated entities; bytes and quality are spread over the hours each session was connected. --room-sums adds the room size and duration sums; --five-minute-rollups adds analytics_5min (lifecycle counters, the participants.connected gauge, bytes and quality per five minutes) inside the 5-minute rollup window. analytics_daily gets no TTL index: daily rollups are kept forever. generate() takes the same switches as rollups: { fiveMinute, nodes, roomSums }.
  • nodes (3 nodes) and schema_meta (schema, retention, capabilities, config).

Documents are inserted in batches of 5 000 with insertMany(ordered: false). The output shows progress and a final summary with documents per collection, elapsed time and inserts per second. The generator keeps only one room in memory at a time, so scenario L fits in a few hundred MB of heap.

Files

File Role
src/schema.ts Collections, indexes and validators of the contract, createCollections() with the fallback
src/contract.ts Stored shape of a model document: bookkeeping removed, nulls omitted, BSON numeric types
src/model.ts Scenarios, document types and the per-room entity generator
src/derive.ts Raw events, stats samples and rollups derived from a generated room
src/generator.ts generate(db, options) and the batched writer
src/generate.ts Generator CLI
src/context.ts queryContext(db): data range and sample identifiers for query plan tests
src/plan.ts Explain summaries: plan stages, indexes, documents examined
src/random.ts mulberry32 generator and sampling helpers
src/args.ts CLI argument parsing