### Run eventgate-devserver locally Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Local_development_setup Commands to install dependencies and start the eventgate-devserver for manual development environments. ```bash $ cd extensions/EventLogging/devserver $ npm install --no-optional $ npm run eventgate-devserver ``` -------------------------------- ### Install TestKitchen Extension Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Local_development_setup Clone the TestKitchen extension repository into the extensions folder of your MediaWiki installation. ```bash git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/TestKitchen ``` -------------------------------- ### Example Schema with Multiple Fragments Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Analytics Example demonstrating how to combine multiple schema fragments for an A/B test scenario. ```APIDOC ### Example 1 Suppose we're running an A/B test on a new default skin for anonymous users and we are interested in measuring session length and average number of visited _articles_ per session. The schema would use the following fragments: core identifiers, page, UI, and A/B testing via: ```yaml allOf: - $ref: /fragment/analytics/common/1.0.0# - $ref: /fragment/analytics/web_identifiers/1.0.0# - $ref: /fragment/analytics/mediawiki_page/1.0.0# - $ref: /fragment/analytics/ui/1.0.0# - $ref: /fragment/analytics/ab_testing/1.0.0# ``` And the following fields would need to be included in the one (1) event logged by the instrument on every page load: ```yaml required: - client_dt - web_session_id - web_pageview_id - page_namespace - ui_screen - test_name - test_group ``` ``` -------------------------------- ### Example Application Log Output Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Troubleshooting Sample output from application logs showing git unified diffs for configuration changes. ```text ...varnish diff: --- +++ @@ -1,500 +1,500 @@ { "fy2025-26-we3.1-image-browsing-ab-test": { "domains": { ... }, "end": "2025-11-12T14:30:00Z", - "start": "2025-11-08T14:30:00Z" + "start": "2025-11-06T14:30:00Z" } } 2025-11-06 23:22:48,309 - INFO - fields: xlab-mw-module-loaded-v2 2025-11-06 23:22:48,309 - INFO - IRC sending: !log Test Kitchen edge-unique experiments (poll 1536) - adds: none; removes: none; fields: xlab-mw-module-loaded-v2 - xLab/MPIC/TK tips at https://w.wiki/FwuD 2025-11-06 23:31:01,481 - INFO - Service alive with checks so far: 1560 ``` -------------------------------- ### Install Fresh Tool for JavaScript Environment Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Maintainer_introduction Installs the Fresh tool, which provides a Docker container with pre-installed developer tools like Node.js and headless browsers for the JavaScript library. Run this command in your terminal. ```bash curl -fsS 'https://gerrit.wikimedia.org/g/fresh/+/23.08.1/bin/fresh-install?format=TEXT' | base64 --decode | python3 ``` -------------------------------- ### Start ClickThroughRateInstrument with Experiment Data Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Measuring_clickthrough_rates Use this snippet to attach a ClickThroughRateInstrument to elements for experiment data collection. It requires the 'ext.wikimediaEvents.testKitchen' module and ensures the experiment is active before starting the instrument. ```javascript const { ClickThroughRateInstrument } = require( 'ext.wikimediaEvents.testKitchen' ); mw.loader.using( 'ext.testKitchen' ).then( () => { const experiment = mw.testKitchen.getExperiment( 'event-participant-count' ); if ( experiment.isAssignedGroup( 'control', 'show' ) ) { $( 'a.ext-campaignevents-events-list-link' ).each( ( index, element ) => ClickThroughRateInstrument.start( 'a.ext-campaignevents-events-list-link:nth-of-type(' + ( index + 1 ) + ')', 'Collaboration list event link', experiment ) ); } } ); ``` -------------------------------- ### Update Instrument Start Date in Test Kitchen DB Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Local_development_setup Use `docker compose exec` and `mariadb` to update the `utc_start_dt` for an instrument if validation prevents setting a start date before today. ```bash $ docker compose exec test-kitchen-db bash $ mariadb -umaria -pmaria MariaDB [(none)]> update test_kitchen.instruments set utc_start_dt = '2026-03-11 14:30:00' where id=...; ``` -------------------------------- ### Example Schema with Multiple Fragments Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Analytics/Fragments An example demonstrating how to combine multiple schema fragments, including common, web identifiers, page, UI, and A/B testing, for a specific analytics use case. ```APIDOC ## Example 1 Suppose we're running an A/B test on a new default skin for anonymous users and we are interested in measuring session length and average number of visited _articles_ per session. The schema would use the following fragments: core identifiers, page, UI, and A/B testing via: ```yaml allOf: - $ref: /fragment/analytics/common/1.0.0# - $ref: /fragment/analytics/web_identifiers/1.0.0# - $ref: /fragment/analytics/mediawiki_page/1.0.0# - $ref: /fragment/analytics/ui/1.0.0# - $ref: /fragment/analytics/ab_testing/1.0.0# ``` And the following fields would need to be included in the one (1) event logged by the instrument on every page load: ```yaml required: - client_dt - web_session_id - web_pageview_id - page_namespace - ui_screen - test_name - test_group ``` ``` -------------------------------- ### Limit metric to experiment cohort duration Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Automated_analysis_of_experiments Example of using the start_date parameter to restrict a metric calculation to a specific time window relative to the experiment start. ```sql TO_TIMESTAMP('{start_date}') + INTERVAL 72 HOUR ``` -------------------------------- ### A/B Test Data Examples Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Analytics Examples of the 'tests' array structure for A/B testing. The array can be empty, contain a single test, or multiple tests. ```json "tests": [] ``` ```json "tests": [ { "name": "growth-homepage", "group": "control" } ] ``` ```json "tests": [ { "name": "growth-homepage", "group": "variant-1" }, { "name": "growth-help-panel", "group": "variant-2" } ] ``` -------------------------------- ### Start Click-Through Rate Instrument Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Measuring_clickthrough_rates Initializes and starts a ClickThroughRateInstrument for tracking clicks on collaboration event links. Ensure the INSTRUMENT_NAME matches the Test Kitchen UI configuration. ```javascript const { ClickThroughRateInstrument } = require( 'ext.wikimediaEvents.testKitchen' ); const INSTRUMENT_NAME = 'collaboration-list-event-links-ctr'; const instrument = mw.testKitchen.getInstrument( INSTRUMENT_NAME ); $( 'a.ext-campaignevents-events-list-link' ).each( ( index, element ) => ClickThroughRateInstrument.start( 'a.ext-campaignevents-events-list-link:nth-of-type(' + (index + 1) + ')', 'Collaboration list event link', instrument ) ); ``` -------------------------------- ### Launch NodeJS Environment with Fresh Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Maintainer_introduction Launches the NodeJS environment provided by Fresh. After running this command, your bash prompt will change, indicating you are inside the container. You can then install dependencies using npm. ```bash santi@mylaptop ~ % fresh-node # 🌱 Fresh 23.08.1 ░ Node.js 18 ░ npm 9 ░ Firefox 102 ░ Chromium 115 ░ Debian 11 Bullseye # image: docker-registry.wikimedia.org/releng/node18-test-browser:0.0.1 # mount: /santi ➟ /Users/santi (read-write) nobody@e99bb96f8bd0:/santi$ npm install . . . . . . ``` -------------------------------- ### Custom Stream Configuration - PHP Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Measure_product_health Example configuration for a custom stream in PHP. This defines the schema and destination for events. ```php 'mediawiki_product_metrics_your_custom_stream_name' => [ 'schema_title' => 'analytics/product_metrics/web/translation', 'destination_event_service' => 'eventgate-analytics-external', 'producers' => [ 'eventgate' => [ 'enrich_fields_from_http_headers' => [ 'http.request_headers.user-agent' => false, ], ], 'metrics_platform_client' => [ 'provide_values' => [ 'performer_is_logged_in', 'performer_is_temp', 'performer_pageview_id', 'mediawiki_database', ], ], ], ], ``` -------------------------------- ### Publish New Java Release Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Deploy_client_libraries Commands to publish a new release of the Java client library to Maven Central. Requires proper credentials and GPG key setup. ```bash ./mvnw -f java -B -P deploy-central release:clean ``` ```bash ./mvnw -f java -B -P deploy-central release:prepare ``` ```bash ./mvnw -f java -B -P deploy-central release:perform ``` -------------------------------- ### Custom Stream Configuration Example Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Create_an_instrument Define a custom stream configuration, including schema title, destination, and producer-specific settings. This is used when the default stream and schema are insufficient. ```php 'mediawiki_product_metrics_your_custom_stream_name' => [ 'schema_title' => 'analytics/product_metrics/web/translation', 'destination_event_service' => 'eventgate-analytics-external', 'producers' => [ 'eventgate' => [ 'enrich_fields_from_http_headers' => [ 'http.request_headers.user-agent' => false, ], ], 'test_kitchen_client' => [ 'provide_values' => [ 'performer_is_logged_in', 'performer_is_temp', 'performer_pageview_id', 'mediawiki_database', ], ], ], ], ``` -------------------------------- ### Custom Stream Configuration - MediaWiki Config Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Measure_product_health Example of adding a custom stream name to the `$wgTestKitchenExperimentStreamNames` configuration variable in MediaWiki. ```php 'wgTestKitchenExperimentStreamNames' => [ 'default' => [ 'product_metrics.web_base', 'mediawiki.product_metrics.reading_list', 'mediawiki.product_metrics.readerexperiments_imagebrowsing', 'mediawiki.product_metrics.your_custom_stream_name' ], ], ``` -------------------------------- ### Run PHP Development Environment with Docker Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Maintainer_introduction Starts a bash session within the buster-php74 Docker image for PHP development. This is a temporary solution until a dedicated PHP environment is available. It mounts the current directory to /work for persistent changes. ```bash docker run -it -v .:/work docker-registry.wikimedia.org/dev/buster-php74:1.1.0-s2 /bin/bash cd /work rm -r vendor rm composer.lock ``` -------------------------------- ### Log IRC Message from wmftkbot Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Troubleshooting This is an example of a log message generated by the wmftkbot on Libera IRC, indicating changes to experiment configurations in Test Kitchen. It shows additions, removals, and modified fields for experiments. ```log wmftkbot https://toolsadmin.wikimedia.org/tools/id/tk !log Test Kitchen edge-unique experiments (poll 4689) - adds: none; removes: none; fields: fy2025-26-we3.1-image-browsing-ab-test, hcaptcha-on-french-wikipedia, xlab-mw-module-loaded-v2 - xLab/MPIC/TK tips at https://w.wiki/FwuD ``` -------------------------------- ### Troubleshoot Test Kitchen Deployment Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Test_Kitchen_UI/Administration Connect to the deployment server, set the specific Kubernetes environment for the next deployment, and list events. This helps in identifying issues during the deployment process. ```bash $ ssh deployment.eqiad.wmnet $ kube-env test-kitchen-next-deploy dse-k8s-eqiad $ kubectl get events ``` -------------------------------- ### View Test Kitchen Logs Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Test_Kitchen_UI/Administration Connect to the deployment server, set the Kubernetes environment, and stream pod logs. This is useful for monitoring application behavior and diagnosing runtime errors. ```bash $ ssh deployment.eqiad.wmnet $ kube_env dse-k8s-eqiad $ kubectl get pods -w $ kubectl logs -f -c --tail=10 ``` ```json {"level":50,"time":1714483575453,"pid":1,"hostname":"test-kitchen-staging-66554859c4-p9m28","msg":"Error while setting an env variable. There is no value for SAL_PASSWORD"} {"level":30,"time":1714483575592,"pid":1,"hostname":"test-kitchen-staging-66554859c4-p9m28","msg":"Connected to the database at an-mariadb1001.eqiad.wmnet:test_kitchen_staging"} {"level":30,"time":1714483575600,"pid":1,"hostname":"test-kitchen-staging-66554859c4-p9m28","msg":"test-kitchen has started listening on port 8080"} ``` -------------------------------- ### Configure Local MediaWiki Event Streams Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Local_development_setup Define the `product_metrics.web_base` stream and other custom streams in your MediaWiki's `LocalSetting.php` file to work with Test Kitchen. ```php $wgEventStreams = [ 'product_metrics.web_base' => [ 'schema_title' => 'analytics/test_kitchen/web/base', 'destination_event_service' => 'eventgate-analytics-external', 'producers' => [ 'metrics_platform_client' => [], ], 'eventgate' => [ 'enrich_fields_from_http_headers' => [ 'http.request_headers.user-agent' => false, ], 'use_edge_uniques' => true, ] ], ]; ``` -------------------------------- ### Deploy Changes with Helmfile Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Test_Kitchen_UI/Administration Use this command to deploy changes to the Test Kitchen environments after preparing and reviewing them. Ensure you are in the correct directory and have pulled the latest changes. ```bash # Do the following once you have prepared the change and the change has been reviewed and merged ssh deployment.eqiad.wmnet cd /srv/deployment-charts git log -n 1 # Check that the change has been pulled cd helmfile.d/dse-k8s-services/ # Check changes and deploy helmfile -e dse-k8s-eqiad diff helmfile -e dse-k8s-eqiad -i apply ``` -------------------------------- ### Configure TestKitchen Extension in LocalSettings.php Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Local_development_setup Load the TestKitchen extension and configure its settings, including the service URL and enabling features like configuration fetching and experiments. ```php // Load the extension ``` ```php wfLoadExtensions( [ // other extensions might be here 'TestKitchen', ] ); ``` ```php // Set the Test Kitchen service URL (this example considers it's running on your localhost) ``` ```php // Linux users might need to use '127.17.0.1' instead of 'host.docker.internal'. The latter doesn't work for some distributions ``` ```php $wgTestKitchenInstrumentConfiguratorBaseUrl = 'http://host.docker.internal:8086'; ``` ```php // Ensures, when testing/debugging with Test Kitchen UI and MediaWiki locally, Test Kitchen API is used ``` ```php $wgTestKitchenEnableConfigsFetching = true; ``` ```php // Enable experimentation capabilities (disabled by default) ``` ```php $wgTestKitchenEnableExperiments = true; ``` -------------------------------- ### Allow-list Stream in InitialiseSettings.php Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Conduct_an_experiment Add the stream name to the Test Kitchen experiment stream allow-list. ```php 'wgTestKitchenExperimentStreamNames' => [ 'default' => [ // ... 'mediawiki.product_metrics.translation_mint_for_readers.experiments', ], ], ``` -------------------------------- ### Bad Use of action_context: Data Stuffing Example Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Decision_Records/Increase_action_context_limit This example shows a poor use of action_context, where excessive and potentially unnecessary data is stuffed into the field, including page details, user interaction metrics, and system information. ```json { "action": "click", "action_source": "get_support", "action_context": { "page_name": "Special:Preferences", "scroll_position": 342, "mouse_x": 1024, "mouse_y": 768, "time_on_page": 47, "previous_5_pages": [...], "browser_memory_usage": "245MB", "cpu_usage": "23%", "network_speed": "4G" } } ``` -------------------------------- ### Donation Event Data Structure Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Automated_analysis_of_experiments/Prepared_metrics Example JSON schema for donation events used in product metrics. ```json { "$schema": "/analytics/product_metrics/web/base/1.4.1", "meta": { "stream": "product_metrics_web_base" }, "action": "donate", "action_subtype": "amount", "action_context": "123.45", "instrument_name": "Donation processor", "experiment": { "coordinator": "default", "enrolled": "{experiment_machine_name}", "assigned": "{group_machine_name} } } ``` -------------------------------- ### mw.testKitchen.getExperiment Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/SDK/JavaScript_SDK Retrieves an instance of an existing experiment based on the configuration defined in the Test Kitchen UI. ```APIDOC ## mw.testKitchen.getExperiment ### Description Get an instance of an existing Experiment according to the configuration defined in Test Kitchen UI. ### Parameters #### Path Parameters - **experimentName** (string) - Required - Name of the experiment ``` -------------------------------- ### Fetch and verify client library with maintenance scripts Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Deploy_client_libraries Use these commands to update and verify the EventLogging extension's foreign resources. ```bash $ php maintenance/run.php ./maintenance/manageForeignResources.php --extension EventLogging update $ php maintenance/run.php ./maintenance/manageForeignResources.php --extension EventLogging verify ... verifying 'metrics-platform' ``` -------------------------------- ### Configure Docker Compose for Test Kitchen Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Local_development_setup Add `test-kitchen` and `test-kitchen-db` services to your `docker-compose.override.yml` to enable the Test Kitchen UI and API for local development. ```yaml services: eventlogging: build: "./extensions/EventLogging/devserver" volumes: - "./cache/events.json:/opt/eventlogging/events.json" - "./cache/eventgate.config.yaml:/opt/eventlogging/eventgate.config.yaml" - "./cache/primary:/opt/eventlogging/primary" - "./cache/secondary:/opt/eventlogging/secondary" ports: - "8192:8192" test-kitchen: extends: file: ./extensions/TestKitchen/devserver/docker-compose.yml service: test-kitchen test-kitchen-db: extends: file: ./extensions/TestKitchen/devserver/docker-compose.yml service: test-kitchen-db volumes: - ./cache/test-kitchen-db:/var/lib/mysql ``` -------------------------------- ### Get Server-Side Experiment Object Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Conduct_an_experiment Retrieve the experiment object server-side to access experiment details. Requires the ExperimentManager service. ```php const EXPERIMENT_NAME = 'larger-default-font-size'; const TREATMENT_GROUP_NAME = 'x-large'; $experimentManager = MediaWikiServices::getInstance()->getService( 'TestKitchen.Sdk.ExperimentManager' ); $experiment = $experimentManager->getExperiment( EXPERIMENT_NAME ); ``` -------------------------------- ### Get Client-Side Experiment Object Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Conduct_an_experiment Retrieve the experiment object client-side to access experiment details. This is used for client-side feature toggling and analytics. ```javascript const EXPERIMENT_NAME = 'larger-default-font-size'; const TREATMENT_GROUP_NAME = 'x-large'; // only needed for feature toggling, not analytics const experiment = mw.testKitchen.getExperiment( EXPERIMENT_NAME ); ``` -------------------------------- ### Good Use of action_context: Timed Ticks Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Decision_Records/Increase_action_context_limit Example of using action_context for measuring session length with timed ticks. The context includes the time in seconds. ```json {"action": "tick", "action_context": {"time_s":}} ``` -------------------------------- ### Misconfigured EventStreamConfig for MinT Experiment Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Incident_reports/2025-09-17_MinT_for_Readers_AA_test_missing_subject_IDs Example of an incorrect stream configuration where the EventGate settings were placed in the wrong stanza, preventing proper subject ID hoisting. ```php // https://gerrit.wikimedia.org/g/operations/mediawiki-config/+/acad29faf2f945642ef0f45cf5a9569b41a10fba/wmf-config/ext-EventStreamConfig.php#2388 'mediawiki.product_metrics.translation_mint_for_readers.experiments' => [ 'schema_title' => 'analytics/product_metrics/web/translation', 'destination_event_service' => 'eventgate-analytics-external', 'producers' => [ 'eventgate' => [ 'enrich_fields_from_http_headers' => [ 'http.request_headers.user-agent' => false, ], ], 'metrics_platform_client' => [ 'provide_values' => [ 'mediawiki_database', 'mediawiki_skin', 'mediawiki_site_content_language', 'mediawiki_site_content_language_variant', 'page_content_language', 'agent_client_platform', 'agent_client_platform_family', 'performer_session_id', 'performer_active_browsing_session_token', 'performer_is_logged_in', 'performer_is_temp', 'performer_language', 'performer_language_variant', 'performer_pageview_id', ], ], ], 'eventgate' => [ 'enrich_fields_from_http_headers' => [ // Don't collect the user agent 'http.request_headers.user-agent' => false, ], 'use_edge_uniques' => true, ], ], ``` -------------------------------- ### Send Event with JS Test Kitchen SDK Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Local_development_setup Instantiate an instrument using the `mw.testKitchen.getInstrument` method and send an event with `myInstrument.send()` within the `ext.testKitchen` module. ```javascript mw.loader.using( 'ext.testKitchen' ).then( () => { const myInstrument = mw.testKitchen.getInstrument( 'my-experiment' ); myInstrument.send( 'some_action' ); } ); ``` -------------------------------- ### Define a custom schema in YAML Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Custom_schemas Example of a custom schema definition combining common, platform, and custom fragments. Replace x.x.x with the appropriate fragment versions. ```yaml title: analytics/product_metrics/web/translation description: Web schema for wiki tranlation workflows. $id: /analytics/product_metrics/web/translation/1.0.0 $schema: 'https://json-schema.org/draft-07/schema#' type: object allOf: - $ref: /fragment/analytics/product_metrics/common/x.x.x - $ref: /fragment/analytics/product_metrics/web/x.x.x - $ref: /fragment/analytics/product_metrics/translation/1.0.0 ``` -------------------------------- ### Querying the Experiment Journal Database Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Troubleshooting SQL commands to query the instruments_history table in the Test Kitchen production database. Requires production Kubernetes access. ```sql stat1010.eqiad.wmnet $ mysql -h an-mariadb1001.eqiad.wmnet -u test_kitchen_production -p mysql> USE test_kitchen_production; DESCRIBE instruments_history SELECT * FROM instruments_history WHERE \G; ``` -------------------------------- ### Override Enrollment via URL Query Parameter Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Conduct_an_experiment Example of using a URL query parameter to force enrollment in a specific experiment group for the current page view. ```text ?mpo=larger-default-font-size:x-large ``` -------------------------------- ### Submit Click Event with Java SDK Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/SDK/Java_SDK Use this snippet to submit a click event using the Test Kitchen base schemas. It requires instantiation of a MetricsClient and provides parameters for client and interaction data. ```java // Parameters derived from client at instantiation of the Metrics Client object with options to pass in dynamic arguments at the time of event submission ClientData clientData = new ClientData( agentData, pageData, mediawikiData, performerData, ); InteractionData interactionData = new InteractionData( 'action_value', 'action_subtype_value', 'action_source_value', 'action_context_value', ); metricsClient.submitClick(clientData, interactionData); ``` -------------------------------- ### Initialize Experiment with Custom Schema and Stream Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Conduct_an_experiment Overrides the default schema and stream for an experiment to ensure data is routed to the correct analytics destination. ```javascript const experiment = mw.testKitchen.getExperiment( EXPERIMENT_NAME ); experiment.setSchema( '/analytics/product_metrics/web/translation/1.4.2' ); experiment.setStream( 'mediawiki.product_metrics.translation_mint_for_readers.experiments' ); ``` -------------------------------- ### Query Event Data in Hive using spark3-sql Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Measure_product_health Use `spark3-sql` to query Hive tables for instrument data. This example counts events from the `product_metrics_web_base` table for a specific date. ```bash $ spark3-sql $ select count(*) from event.product_metrics_web_base where year = 2025 and month = 11 and day = 05; ``` -------------------------------- ### Update Java Client Library Version Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Deploy_client_libraries Example of updating the version number in the Maven project's pom file for a major version bump of the Java client library. ```xml org.wikimedia.metrics metrics-platform 3.0-SNAPSHOT ``` -------------------------------- ### Querying Nested JSON Example Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Decision_Records/Increase_action_context_limit Demonstrates a verbose and error-prone SQL-like query for extracting data from a deeply nested JSON field, highlighting the difficulties caused by data stuffing. ```sql CAST(GET_JSON_OBJECT(action_context, '$.timing_ms') AS INT) ``` -------------------------------- ### Good Use of action_context: Article Count Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Decision_Records/Increase_action_context_limit Example demonstrating how to use action_context to record the number of articles in a reading list when a user adds another. The context captures the article count. ```json {"action": "click", "action_subtype": "save_article_to_reading_list", "action_context": {"article_count": }} ``` -------------------------------- ### Configure Event Stream in ext-EventStreamConfig.php Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Conduct_an_experiment Define the stream name, schema, and producer settings including edge unique configuration. ```php 'wgEventStreams' => [ 'default' => [ // ... // Stream name. 'mediawiki_product_metrics_translation_mint_for_readers_experiments' => [ // Schema name. 'schema_title' => 'analytics/product_metrics/web/translation', 'destination_event_service' => 'eventgate-analytics-external', 'producers' => [ 'eventgate' => [ 'enrich_fields_from_http_headers' => [ // Collect the user agent. // Disabled by default. 'http.request_headers.user-agent' => 'user-agent', ], // Target logged-out users. 'use_edge_uniques' => true, ], 'metrics_platform_client' => [ // Contextual attributes. // See https://wikitech.wikimedia.org/wiki/Experimentation_Lab/Contextual_attributes // NOTE `agent_client_platform` and `agent_client_platform_family` // are automatically added. 'provide_values' => [ // We recommend collecting `performer_is_logged_in` and `performer_is_temp` at the same time. // See https://phabricator.wikimedia.org/T374812#10953216 'performer_is_logged_in', 'performer_is_temp', 'performer_pageview_id', 'mediawiki_database', ], ], ], ], ], ], ``` -------------------------------- ### Enable Contextual Attributes in Event Stream Configuration Source: https://wikitech.wikimedia.org/wiki/Test_Kitchen/Contextual_attributes Configure an event stream to collect specific contextual attributes by listing them in the 'provide_values' array. This example enables 'page_id', 'page_title', 'performer_is_logged_in', and 'performer_is_temp'. ```php // … 'mediawiki.interwiki_link_hover' => [ 'schema_title' => 'analytics/product_metrics/web/base', 'destination_event_service' => 'eventgate-analytics-external', 'producers' => [ 'metrics_platform_client' => [ // Contextual attributes to add to the event before it is submitted to this stream. 'provide_values' => [ "page_id", "page_title", // We recommend collecting the performer_is_logged_in and performer_is_temp // attributes at the same time. See https://phabricator.wikimedia.org/T374812#10953216 "performer_is_logged_in", "performer_is_temp", ], ], ], ], // … ```