Metrics Platform/How to/Validate Events

From Wikitech

Test event validation

During active development, it is important to be able to test that events can be validated by EventGate against a specified JSONSchema. Each of the client libraries contain unit and integration tests for ensuring that events are properly formatted and serialized for submission. However testing end-to-end is a valuable exercise in instilling confidence that events will be produced to Kafka and ensuing data is able to be consumed.

The basic process for testing end-to-end requires having a local EventGate instance. See Metrics_Platform#Quick_Start for development environment recommendations.

Javascript

Because the Javascript client library is provided through the MediaWiki EventLogging extension, having an instance of MediaWiki running in a local development environment is required. Once a change set is submitted as a patch to the EventLogging extension (presumably after corresponding changes have been merged in the Javascript client library), the following steps should be followed:

$wgEventStreams = [
  'test.metrics_platform.interactions' => [
    'schema_title' => '/analytics/product_metrics/web/base',
    'destination_event_service' => 'eventgate-analytics-external',
    'producers' => [
      'metrics_platform_client' => [
        'provide_values' => [
          'performer_is_logged_in',
          'mediawiki_skin',
        ],
      ],
    ],
  ],
];

// When $wgEventLoggingStreamNames is false (not falsy), the EventLogging
// JavaScript client will treat all streams as if they are configured and
// registered.
$wgEventLoggingStreamNames = [ 'test.metrics_platform.interactions' ];
mw.eventLog.submitInteraction('test.metrics_platform.interactions', '/analytics/product_metrics/web/base/1.0.0', 'init');
  • Observe that an event has been sent to, validated and accepted by the local EventGate instance.

Source: https://phabricator.wikimedia.org/T351293#9337205

PHP

Java

While the Java client library includes end-to-end integration testing from reading a local stream config data fixture to building a metrics client to submitting events and then stubbing expected responses, it does not ultimately provide a true end-to-end testing experience wherein production config is read and the metrics client submits an event to EventGate whereupon it is validated and accepted.

To emulate this testing scenario, we can create a test that instantiates a metric client which fetches production stream configs (from the meta api) and submits an event using a production stream associated with a production schema and have the event validated with a local EventGate instance.

By using production config, we can submit an event using an example stream:

@Test void submitEventTimerStreamConfig() throws IOException, InterruptedException {
        // Create the metrics client.
        MetricsClient testMetricsClient = MetricsClient.builder(testClientData).build();
        await().atMost(10, SECONDS).until(testMetricsClient::isFullyInitialized);

        testMetricsClient.submitInteraction(
                "android.metrics_platform.find_in_page_interaction",
                DataFixtures.getTestClientData(getExpectedEventClick()),
                DataFixtures.getTestInteractionData("TestClick")
        );
        Thread.sleep(10_000);
        await().atMost(30, SECONDS).until(() -> testMetricsClient.getEventQueue().size() == 0);
    }

In the example above, the MetricsClient::submitInteraction() method takes the sample production stream name as a parameter along with some test ClientData and test InteractionData. The default schema id is set as the app base schema inside the library.

Once the metrics client has fetched the production stream configs, it batch processes the event queue to send serialized events to the DestinationEventService which in this case should be set as a local EventGate instance.

Because the sample production stream android.metrics_platform.find_in_page_interaction adds only a few requested values in its producer config, we can prevent ContextController:enrichEvent() (which enriches the event with configuration-specified contextual values) from filtering the ClientData and simply have all available contextual values sent with the event by commenting out the lines the method that resets the ClientData.

The test above waits until the event queue is empty so the following method can be added to the MetricsClient class though it is not currently in the latest release:

public BlockingQueue<EventProcessed> getEventQueue() {
    return this.eventQueue;
}

Make sure local eventlogging is running and then run the test. Observe that the test event is sent to and validated/accepted by the local EventGate instance:

Source: https://phabricator.wikimedia.org/T351292#9347381

Troubleshooting

If one is using Docker for the local EventGate instance and has it running on port 8192, note that WireMock also runs on this port so lines related to WireMock need to be commented out as well. Otherwise try running a local EventGate on a different port.