Background
Quick background, we have two major types of javascript that our customers and partners may use: analytics tags and ad tags. Both tags are javascript and share the same error capture code.
Another quick note is that we run on Amazon Web Services so this approach is based on some of these services including S3, CloudFront and EMR.
Implementation
Our client side JS is compiled from Coffeescript. I've created a couple of gists to show you what the error logging code looks like in Coffeescript.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Simple error log that uses pixels with a query string to send error information | |
class ErrorLog | |
@log: (context, error_data, loggers...) -> | |
logger.log(context, error_data) for logger in loggers | |
class BaseLogger | |
@map_error_data: (error_data, seperator, func = (val) -> val) -> | |
("#{k}=#{func(v)}" for k, v of error_data).join(seperator) | |
class PixelLogger extends BaseLogger | |
@http_host: "http://YOUR_HTTP_HOST" | |
@https_host: "https://YOUR_HTTPS_HOST" | |
@set_pixel_path: (pixel_path) -> | |
@pixel_path = pixel_path | |
@log: (context, error_data) -> | |
log_path = if context.win.location.protocol == "https:" then @https_host else @http_host | |
msg = @map_error_data(error_data, "&", encodeURIComponent) | |
pixel = new Image(1,1) | |
pixel.src = "#{log_path}/#{@pixel_path}?#{msg}" | |
pixel | |
class ConsoleLogger extends BaseLogger | |
@log: (context, error_data) -> | |
msg = @map_error_data(error_data, ", ") | |
console.log(msg) if console? && console.log? | |
# used for local testing | |
class LocalLogger extends BaseLogger | |
@errors: [] | |
@log: (context, error_data) -> | |
@errors.push(error_data) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class AdTagErrorLog | |
@log : (context, error)-> | |
error_data = { | |
tag_type: "ad_tags", | |
pid: context.win._bizo_ad_partner_id | |
section_id: context.win._bizo_ad_section_id, | |
ad_width: context.win._bizo_ad_width, | |
ad_height: context.win._bizo_ad_height, | |
ref: context.doc.referrer, | |
error: error | |
} | |
PixelLogger.set_pixel_path("ad_tags/error.gif") | |
ErrorLog.log(context, error_data, PixelLogger) | |
if(context.win._bizo_debug == true) | |
context.win.LocalLogger = LocalLogger | |
ErrorLog.log(context, error_data, ConsoleLogger, LocalLogger) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#... snipped for brevity | |
try | |
context = new Context(document, window) | |
new AdTags(context).execute() | |
catch e | |
AdTagErrorLog.log(new Context(document, window), e) |
Details
The example shows our ad tags trying to execute surrounded by a try/catch that captures the error and eventually results in loading an image appending the relevant error metadata.
AWS Details
The image that is loaded actually lives on CloudFront. The CloudFront distribution is setup with logging which means that requests are logged and delivered to a specified S3 bucket (usually within 24 hours). Every day we run an EMR job against the CloudFront request logs that generates a report summarizing the errors. And that is it. Pretty simple and this approach has worked for us.
Pre-emptive "this isn't perfect" response
Some of you may be thinking, "you may not get all requests!". CloudFront logs are not supposed to be used for 100% accurate reporting (although nothing is really 100%). In our case, we don't need to capture all errors rather we are looking for directional information.
No comments:
Post a Comment