Files
svc-api-x/v1/taffy/bonus/LogToBugsnag.cfc

132 lines
4.2 KiB
Plaintext

/**
* Adapter Path: taffy.bonus.LogToBugsnag
* Configuration Options: (structure)
*
* variables.framework.exceptionLogAdapterConfig = {
* apiKey = "c9d60ae4c7e70c4b6c4ebd3e8056d2b8",
* appVersion = "1.1.3",
* releaseStage = "production"
* };
*
* apiKey: The API Key associated with the project
* appVersion: The version number of the application which generated the error
* releaseStage: The release stage that this error occurred in (e.g "development", "staging" or "production")
*/
component implements="taffy.bonus.ILogAdapter" {
/**
* Initializes this logger
*/
public function init(config, tracker="") hint="I accept a configuration structure to setup and return myself" {
variables.config = {};
structAppend(variables.config, arguments.config, true);
return this;
}
/**
* Logs or notifies the specified exception
*/
public function saveLog(exception) hint="I log or otherwise notify you of an exception" {
var payload = {};
// Add Project API key to payload
payload["apiKey"] = variables.config.apiKey;
// Add notifier info to payload
payload["notifier"] = {};
payload["notifier"]["name"] = "Taffy";
payload["notifier"]["version"] = "1.0";
payload["notifier"]["url"] = "https://github.com/atuttle/Taffy";
// Add exception details to payload
payload["events"] = [];
payload["events"][1] = {};
payload["events"][1]["payloadVersion"] = "2";
payload["events"][1]["exceptions"] = [];
payload["events"][1]["exceptions"][1] = convertException(arguments.exception);
// Add application details to payload
payload["events"][1]["app"] = {};
payload["events"][1]["app"]["appVersion"] = variables.config.appVersion;
payload["events"][1]["app"]["releaseStage"] = variables.config.releaseStage;
// Add some metadata to payload
payload["events"][1]["metaData"] = {};
payload["events"][1]["metaData"]["request"] = {};
payload["events"][1]["metaData"]["request"]["remoteAddr"] = cgi.remote_addr;
payload["events"][1]["metaData"]["request"]["requestMethod"] = cgi.request_method;
payload["events"][1]["metaData"]["request"]["requestUrl"] = cgi.request_url;
// Send log to Bugsnag
cfhttp(url="https://notify.bugsnag.com", method="post") {
cfhttpparam(type="header", name="Content-Type", value="application/json");
cfhttpparam(type="body", value=serializeJSON(payload));
}
}
/**
* Converts the specified exception to be added to the payload
*/
private struct function convertException(required struct exception) output="false" {
var root = "";
var exceptionElement = {};
var tagContextElement = "";
// Get the root exception
if (structKeyExists(exception, "rootCause")) {
root = arguments.exception.rootCause;
} else {
root = arguments.exception;
}
// Add type and message to payload
exceptionElement["errorClass"] = root.type;
exceptionElement["message"] = root.message;
// Build stack trace
exceptionElement["stacktrace"] = [];
for (tagContextElement in root.TagContext) {
arrayAppend(exceptionElement["stacktrace"], convertTagContextElement(tagContextElement));
}
return exceptionElement;
}
/**
* Converts the specified Tag Context element to be included in the stack trace array
*/
private struct function convertTagContextElement(required struct tagContextElement) output="false" {
var stackTraceElement = {};
// Add stack trace data
stackTraceElement["file"] = arguments.tagContextElement.template;
stackTraceElement["lineNumber"] = arguments.tagContextElement.line;
stackTraceElement["columnNumber"] = arguments.tagContextElement.column;
stackTraceElement["method"] = "Unknown function";
// Add code details
if (structKeyExists(arguments.tagContextElement, "codePrintPlain")) {
stackTraceElement["code"] = convertCodePrint(arguments.tagContextElement.codePrintPlain);
}
return stackTraceElement;
}
/**
* Converts the specified code details to be included to the stack trace element
*/
private struct function convertCodePrint(required string codePrintText) output="false" {
var codeLines = {};
var split = listToArray(arguments.codePrintText, chr(10));
var line = "";
// Add code lines
for (line in split) {
structInsert(codeLines, listFirst(line, ":"), trim(listRest(line, ":")));
}
return codeLines;
}
}