Analytics/Archive/Pixel Service

From mediawiki.org

This page is archived! Find up-to-date documentation at https://wikitech.wikimedia.org/wiki/Analytics

The Pixel service is the "front door" to the analytics system: a public endpoint with a simple interface for getting data into the datastore.

Components[edit]

  • Request Endpoint: HTTP server that handles GET requests to the <blink>PIXEL</blink> service endpoint, responding with 204 NO CONTENT or an actual, honest-to-god 1x1 transparent gif. Data is submitted into the cluster via query parameters.
  • Messaging System: routes messages (request information + data content) from the request endpoint to the datastore. This component is intended to be implemented by Apache Kafka.
  • Datastore Consumer: consumes messages, shunting them into the datastore utilizing HDFS staging and/or append.
  • Processing Toolkit: a standard template for a pig job to process (count, aggregate, etc) event data query string params, handling standard indirection for referrer and timestamp, Apache Avro de/serialization, and providing tools for conversion funnel and A/B testing analysis.
  • Event Logging Library: a JS library with an easy interface to abstract the sending of data to the service. Handles event data conventions for proxied timestamp, referrer; normal web request components.

Service prototype[edit]

To get up and running right away, we're going to start with an alpha prototype, and work with teams to see where it goes.

  • /event.gif on bits multicast stream -> udp2log (1:1) running in Analytics cluster
    • Until bits caches are ready, we'll also have a publicly accessible endpoint on analytics1001
  • Kafka consumes udp2log, creating topic per product-code -- no intermediate aggregation at cache DC
  • Cron to run Kafka-Hadoop consumer, importing all topics into Hadoop to datetime+producer-code paths

EventLogging Integration TODOs[edit]

  • Make sure all event data goes into Kraken (I think it may only be esams at the moment, not sure). [ottomata] (Dec)
  • Divvy up some TODOs with Ori:
    • Keeping udplog seq id counters for each bits host and emitting some alert if gaps detected
    • Until https://rt.wikimedia.org/Ticket/Display.html?id=4094 is resolved, monitor for truncated URIs (detectable because missing trailing ';') and set up some alerting scheme
    • Speaking of that RT ticket: check w/Mark if we can do something useful to move that along (like update the patch so it applies against the versions deployed to prod).
  • Figure out a useful arrangement for server-side events (basic idea: call wfDebugLog(..) on hooks that represent "business" events, have wfDebugLog write to UDP / TCP socket pointing at Kraken. See EventLogging extension for some idea of what I mean.
  • Things Ori needs and would repay in dev time and/or sexual favors: - Puppetization of stuff on Vanadium - Help w/MySQL admin
  • Other EventLogging TODOs: mw:Extension:EventLogging/Todos
          • Figure out how to map event schemas to Avro(?) or some other way to make Hadoop schema-aware so the data is actually useful rather than just blob-like

Getting to production[edit]

We're pretty settled on Kafka as the messaging transport, but to use the dynamic load-balancing and failover features we need a ZooKeeper-aware producer — unfortunately, only the Java and C# clients have this functionality. (This is a blocker for both the Pixel Service AND general request logging.)

Three options:

  1. Pipe logging output from Squid & Varnish into the console producer (which implies running the JVM in production);
  2. Write code (a Varnish plugin plus configuration as described here, as well as a Squid module, both in something C-like) to do ZK-integration and publish to Kafka
  3. Continue to use udp2log -> Kafka with the caveat that the stream is unreliable until it gets to Kafka.

Frequently Asked Questions[edit]

What HTTP actions will the service support?[edit]

GET.

What about POSTs?[edit]

No POST. Only GET. Other than content-length, there's no real justification for a POST, and if you're sending strings that are greater than 2k, you kind of already have a problem.

Can I send JSON?[edit]

Sure, but we're probably not going to do anything special with it -- the JSON values will show up as strings that you'll have to parse to aggregate, count, etc. Ex: GET /event.gif?json=={"foo":1,"bar":[1,2,3]} (and recall you'll have to encodeURIComponent(json)).

As we want to build tools to cover the normal cases first, this is not really recommended. (Just use www-form-encoding KV pairs as usual.) If anyone has a REEEEALLY good use-case, we can talk about having a key-convention for sending a json payload, like, say, calling the key json.

If I send crazy HTTP headers, will the service record them?[edit]

No. We will not parse anything other than the query string.

Custom headers are exactly what we want to avoid -- think of the metadata in an HTTP request as being an interface. You want it to be minimal and well-defined, so little custom parsing needs to occur. KV-pairs in the query string are both flexible and generic enough to meet all reasonable use-cases. If you really need typing, send JSON as the value (as mentioned above).

See also[edit]