{"_id":"56fc65a04388650e00eb45cc","version":{"_id":"564e5a9b1560880d008d30dc","project":"564e5930c3553e0d003e53d0","__v":22,"createdAt":"2015-11-19T23:26:19.166Z","releaseDate":"2015-11-19T23:26:19.166Z","categories":["564e5a9b1560880d008d30dd","566318e1f5ca460d00f41896","56631d08cd54d50d005015fa","56631d2a81ad7417006a202c","5668ba19fbd7680d009375f4","5668cb8b10bda80d00797ed9","5668cb9d10bda80d00797eda","56830d8a3f94e00d004e2a7a","56830d9072bb720d0091f594","56830d94cb4d190d0027698e","56830dc44aecbd0d00a464c5","569e90f3c9b43e0d00c4bab1","56a96d338791090d00113bab","56b12d8336d2580d00247877","56c36bf0a869d017002ea55b","56c36bf93d30210d00ea84bb","56c77749b935671700ff0304","56c7ab9e5652c217008e091a","56cb8bdad5c6241d00ef5e61","58aefce02470660f00b54539","58aefd0bebd7370f0078b954","59ca65ca4337830026edf24f"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"Foundation","version_clean":"2.0.0","version":"2"},"category":{"_id":"56c77749b935671700ff0304","__v":6,"pages":["56c777aec2f82e0d00d7cfc4","56cf5f668629f91300fd97ce","56d00c374a03c00b00a07c03","56d3b713d3f4650b00749658","56d3d74fd3f4650b00749677","56d3d9d20b39260b008da47b"],"project":"564e5930c3553e0d003e53d0","version":"564e5a9b1560880d008d30dc","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-02-19T20:12:57.931Z","from_sync":false,"order":2,"slug":"events-api","title":"Events API v1"},"user":"565f421a7f93280d0052cf6a","__v":26,"project":"564e5930c3553e0d003e53d0","parentDoc":null,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-03-30T23:47:44.223Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":5,"body":"A Custom Event Transform allows users to reliably convert a payload sent by integrations to a payload understood by PagerDuty, using JavaScript (ES5).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Writing your first Custom Event Transform\"\n}\n[/block]\n  * Add a service called the 'Custom Event Transformer'.\n  * Once you have created your service, click on the 'Show JavaScript' button. You have some pre-populated code which would create an event with the raw body of the request in the body. Try it!   Make your integration send a test payload to the integration url.\n  * Once you have sent the test alert, an incident will get triggered. The details in your incident is the raw body of the request that was sent.\n\nAnd that's it! You are ready to write your Custom Event Transform!\n\nTo understand the pre-populated code and how to get your function to emit events to PagerDuty, see [The PD Object](#the-pd-object).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"The PD Object\"\n}\n[/block]\n## Constants\n### Event types\nUse one of these three constants to indicate the type of event in the normalized event.\n\n  * `PD.Trigger` - use this event type to trigger a new event\n  * `PD.Resolve` - use this event type to resolve a triggered incident\n  * `PD.Acknowledge` - use this event type to acknowledge a triggered incident\n\n### The input request\nThis object allows you to access the request that your integration just sent to PagerDuty.\n\n  * `PD.inputRequest.uri` - an object with the details of the URI that the request was sent to\n  * `PD.inputRequest.rawBody` - the raw, unparsed body of the request\n  * `PD.inputRequest.body` - the parsed body of the request, if a supported `Content-Type` was given. Supported `Content-Type`s are `application/json`, `application/x-www-form-urlencoded` and `multipart/form-data`\n  * `PD.inputRequest.headers` - the HTTP headers present in the request\n  * `PD.inputRequest.method` - the HTTP method used to make the request\n\n## Methods\n### PD.assertType\n  * `PD.assertType` is a utility function used to assert the type of a field. If the assertion fails, we will drop the event and the function execution will stop. If the assertion passes, the function execution continues.\n  * Signature: `PD.assertType(type, value, value_human_name)`\n\nExamples:\n  * `PD.assertType(Array, x, \"the key x in object inputRequest.body\")`\n  * `PD.assertType([Boolean, Number], x, \"the key x in object inputRequest.body\")`\n\n### PD.fail\n  * `PD.fail` is used to indicate that the event should be dropped\n  * Signature: `PD.fail(error_message)`\n\nExample:\n  * `PD.fail(“Failed to parse event”)`\n\n### PD.emitGenericEvents\n  * `PD.emitGenericEvents` is used to emit an event or multiple events into the PagerDuty ecosystem\n  * Signature: `PD.emitGenericEvents([the_pagerduty_payload])`\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"The PagerDuty Payload\"\n}\n[/block]\nThe PagerDuty event payload is fairly simple. It is a JSON object in the same form as [accepted by the Events API](doc:trigger-events).\n\nFor convenience, constants are provided for the `event_type` field: `PD.Trigger`, `PD.Acknowledge`, and `PD.Resolve`.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Debug Mode\",\n  \"body\": \"Setting your Custom Event Transform to debug mode allows you to test your universal transform as you write it. If there are any errors in your code, you will still receive a triggered incident with a brief description of the error.\\n\\nYou can set the integration to debug mode by changing the configuration of the service.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Examples\"\n}\n[/block]\nHere's the most basic CET possible.  It triggers on every request to the integration URL -- even opening it up in a web browser.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var normalized_event = {\\n  event_type: PD.Trigger,\\n  description: 'Raw event',\\n  details: PD.inputRequest\\n};\\nPD.emitGenericEvents([normalized_event]);\",\n      \"language\": \"javascript\",\n      \"name\": \"A simple service that passes raw events\"\n    }\n  ]\n}\n[/block]\nThis script triggers an incident from an **SMS** using Twilio.  It event attaches images if you send them.\n[block:html]\n{\n  \"html\": \"<span id=\\\"sms\\\"></span>\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var contexts = [{\\n  \\\"type\\\": \\\"link\\\",\\n  \\\"href\\\": \\\"tel:\\\" + PD.inputRequest.body.From,\\n  \\\"text\\\": \\\"call \\\" + PD.inputRequest.body.From\\n}];\\n\\nif (PD.inputRequest.body.MediaUrl0) {\\n  contexts.push({\\n    \\\"type\\\": \\\"image\\\",\\n    \\\"src\\\": PD.inputRequest.body.MediaUrl0\\n  }); \\n}\\n\\nvar normalized_event = {\\n  incident_key: PD.inputRequest.body.SmsMessageSid,\\n  event_type: PD.Trigger,\\n  description: PD.inputRequest.body.From + \\\" \\\" + PD.inputRequest.body.Body,\\n  contexts: contexts\\n};\\n\\nPD.emitGenericEvents([normalized_event]);\",\n      \"language\": \"javascript\",\n      \"name\": \"Turn an SMS into an incident using Twilio\"\n    }\n  ]\n}\n[/block]\nHere's a simple one from one of our customers to handle webhooks from **ServerGuard24** \n[block:html]\n{\n  \"html\": \"<span id=\\\"serverguard24\\\"></span>\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var webhook = PD.inputRequest;\\nvar event_type = PD.Trigger;\\nif(webhook.body.check_result == \\\"OK\\\") {event_type = PD.Resolve;}\\n\\nvar normalized_event = {\\n  event_type: event_type,\\n  incident_key: webhook.body.server_name,\\n  description: webhook.body.check_output,\\n  details: webhook.body\\n};\\n\\nPD.emitGenericEvents([normalized_event]);\",\n      \"language\": \"javascript\",\n      \"name\": \"ServerGuard24\"\n    }\n  ]\n}\n[/block]\nHere's a proof of concept that our support team wrote that creates PagerDuty incident from an issue in **Visual Studio Team Foundation Server 2015**.\n[block:html]\n{\n  \"html\": \"<span id=\\\"vstfs\\\"></span>\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"function transform(PD) {\\n  var webhook = PD.inputRequest\\n  var body = webhook.body || JSON.parse(webhook.rawBody);\\n\\n  var incident_key = (body.message.markdown||\\\")\\\").split(\\\")\\\")[0]; /*so hacky, but resource.workItemId isn't populated on create*/\\n  var description = body.message.text.split(\\\"\\\\r\\\\n\\\")[0];\\n  var url = null;\\n  if(incident_key.split(\\\"(\\\").length==2) {url = incident_key.split(\\\"(\\\")[1];}\\n\\n  var event_type = PD.Trigger;\\n  try {\\n  if(body.resource.fields[\\\"System.State\\\"].newValue == \\\"Resolved\\\") { event_type = PD.Resolve; }\\n  } catch (e) {}\\n  \\n  \\n  var normalized_event = {\\n    event_type: event_type,\\n    incident_key: incident_key,\\n    description: description,\\n    details: body.resource.fields,\\n    client: \\\"View in Team Foundation Server\\\",\\n    client_url: url\\n  };\\n  PD.emitEvent(normalized_event);\\n}\",\n      \"language\": \"javascript\",\n      \"name\": \"Visual Studio Team Foundation Server 2015\"\n    }\n  ]\n}\n[/block]\nThis script takes **Github** issues and turns them into incidents:\n[block:html]\n{\n  \"html\": \"<span id=\\\"github\\\"></span>\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var webhook = PD.inputRequest.body;\\n\\nvar normalized_event = {\\n  event_type: PD.Trigger,\\n  incident_key: webhook.issue.number,\\n  description: webhook.issue.title,\\n  details: {\\n    description: webhook.body\\n  },\\n  client: \\\"Github issues\\\",\\n  client_url: webhook.issue.url\\n};\\n\\nif(webhook.action==\\\"opened\\\") PD.emitGenericEvents([normalized_event]);\",\n      \"language\": \"javascript\",\n      \"name\": \"Github issues\"\n    }\n  ]\n}\n[/block]\nSome customers have started rewriting our supported integrations.  For instance, here's the start of a CET that will handle **New Relic**'s generic webhooks: \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var normalized_event = {\\n  event_type: PD.Trigger,\\n  incident_key: PD.inputRequest.body.incident_id,\\n  description: PD.inputRequest.body.policy_name+\\\": \\\"+PD.inputRequest.body.details,\\n  details: PD.inputRequest.body,\\n  client: \\\"New Relic\\\",\\n  client_url: PD.inputRequest.body.incident_url\\n};\\n​\\nPD.emitGenericEvents([normalized_event]);\",\n      \"language\": \"javascript\",\n      \"name\": \"Simple New Relic\"\n    }\n  ]\n}\n[/block]\nThis is the CET that Steve demoed on our June \"What's New\" webinar, it takes a **Zapier** webhook triggered from **Instagram** and makes it a PagerDuty incident:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var webhook = PD.inputRequest.body;\\n\\nvar normalized_event = {\\n  event_type: PD.Trigger,\\n  description: 'Incoming kitten from ' + webhook.user.username,\\n  client: 'Instagram',\\n  client_url: webhook.link,\\n  contexts: [{\\n    type: 'image',\\n    src: webhook.images.standard_resolution.url,\\n    href: webhook.link,\\n    alt: webhook.caption.text\\n  }]\\n};\\n\\nif (webhook.caption.text.indexOf('cute') > -1) {\\nnormalized_event.contexts.push({\\n    type: 'link',\\n    href: 'https://broadly.vice.com/en_us/article/why-you-are-addicted-to-cute-baby-animals',\\n    text: '[Runbook] How to handle cuteness overload'\\n  });\\n}\\n\\nPD.emitGenericEvents([normalized_event]);\",\n      \"language\": \"javascript\",\n      \"name\": \"Instagram - Zapier -> PagerDuty\"\n    }\n  ]\n}\n[/block]\n\n[block:html]\n{\n  \"html\": \"<div style='height:50em;'></div>\\n\"\n}\n[/block]","excerpt":"","slug":"creating-an-integration-inline","type":"basic","title":"Custom Event Transforms"}

Custom Event Transforms


A Custom Event Transform allows users to reliably convert a payload sent by integrations to a payload understood by PagerDuty, using JavaScript (ES5). [block:api-header] { "type": "basic", "title": "Writing your first Custom Event Transform" } [/block] * Add a service called the 'Custom Event Transformer'. * Once you have created your service, click on the 'Show JavaScript' button. You have some pre-populated code which would create an event with the raw body of the request in the body. Try it! Make your integration send a test payload to the integration url. * Once you have sent the test alert, an incident will get triggered. The details in your incident is the raw body of the request that was sent. And that's it! You are ready to write your Custom Event Transform! To understand the pre-populated code and how to get your function to emit events to PagerDuty, see [The PD Object](#the-pd-object). [block:api-header] { "type": "basic", "title": "The PD Object" } [/block] ## Constants ### Event types Use one of these three constants to indicate the type of event in the normalized event. * `PD.Trigger` - use this event type to trigger a new event * `PD.Resolve` - use this event type to resolve a triggered incident * `PD.Acknowledge` - use this event type to acknowledge a triggered incident ### The input request This object allows you to access the request that your integration just sent to PagerDuty. * `PD.inputRequest.uri` - an object with the details of the URI that the request was sent to * `PD.inputRequest.rawBody` - the raw, unparsed body of the request * `PD.inputRequest.body` - the parsed body of the request, if a supported `Content-Type` was given. Supported `Content-Type`s are `application/json`, `application/x-www-form-urlencoded` and `multipart/form-data` * `PD.inputRequest.headers` - the HTTP headers present in the request * `PD.inputRequest.method` - the HTTP method used to make the request ## Methods ### PD.assertType * `PD.assertType` is a utility function used to assert the type of a field. If the assertion fails, we will drop the event and the function execution will stop. If the assertion passes, the function execution continues. * Signature: `PD.assertType(type, value, value_human_name)` Examples: * `PD.assertType(Array, x, "the key x in object inputRequest.body")` * `PD.assertType([Boolean, Number], x, "the key x in object inputRequest.body")` ### PD.fail * `PD.fail` is used to indicate that the event should be dropped * Signature: `PD.fail(error_message)` Example: * `PD.fail(“Failed to parse event”)` ### PD.emitGenericEvents * `PD.emitGenericEvents` is used to emit an event or multiple events into the PagerDuty ecosystem * Signature: `PD.emitGenericEvents([the_pagerduty_payload])` [block:api-header] { "type": "basic", "title": "The PagerDuty Payload" } [/block] The PagerDuty event payload is fairly simple. It is a JSON object in the same form as [accepted by the Events API](doc:trigger-events). For convenience, constants are provided for the `event_type` field: `PD.Trigger`, `PD.Acknowledge`, and `PD.Resolve`. [block:callout] { "type": "info", "title": "Debug Mode", "body": "Setting your Custom Event Transform to debug mode allows you to test your universal transform as you write it. If there are any errors in your code, you will still receive a triggered incident with a brief description of the error.\n\nYou can set the integration to debug mode by changing the configuration of the service." } [/block] [block:api-header] { "type": "basic", "title": "Examples" } [/block] Here's the most basic CET possible. It triggers on every request to the integration URL -- even opening it up in a web browser. [block:code] { "codes": [ { "code": "var normalized_event = {\n event_type: PD.Trigger,\n description: 'Raw event',\n details: PD.inputRequest\n};\nPD.emitGenericEvents([normalized_event]);", "language": "javascript", "name": "A simple service that passes raw events" } ] } [/block] This script triggers an incident from an **SMS** using Twilio. It event attaches images if you send them. [block:html] { "html": "<span id=\"sms\"></span>" } [/block] [block:code] { "codes": [ { "code": "var contexts = [{\n \"type\": \"link\",\n \"href\": \"tel:\" + PD.inputRequest.body.From,\n \"text\": \"call \" + PD.inputRequest.body.From\n}];\n\nif (PD.inputRequest.body.MediaUrl0) {\n contexts.push({\n \"type\": \"image\",\n \"src\": PD.inputRequest.body.MediaUrl0\n }); \n}\n\nvar normalized_event = {\n incident_key: PD.inputRequest.body.SmsMessageSid,\n event_type: PD.Trigger,\n description: PD.inputRequest.body.From + \" \" + PD.inputRequest.body.Body,\n contexts: contexts\n};\n\nPD.emitGenericEvents([normalized_event]);", "language": "javascript", "name": "Turn an SMS into an incident using Twilio" } ] } [/block] Here's a simple one from one of our customers to handle webhooks from **ServerGuard24** [block:html] { "html": "<span id=\"serverguard24\"></span>" } [/block] [block:code] { "codes": [ { "code": "var webhook = PD.inputRequest;\nvar event_type = PD.Trigger;\nif(webhook.body.check_result == \"OK\") {event_type = PD.Resolve;}\n\nvar normalized_event = {\n event_type: event_type,\n incident_key: webhook.body.server_name,\n description: webhook.body.check_output,\n details: webhook.body\n};\n\nPD.emitGenericEvents([normalized_event]);", "language": "javascript", "name": "ServerGuard24" } ] } [/block] Here's a proof of concept that our support team wrote that creates PagerDuty incident from an issue in **Visual Studio Team Foundation Server 2015**. [block:html] { "html": "<span id=\"vstfs\"></span>" } [/block] [block:code] { "codes": [ { "code": "function transform(PD) {\n var webhook = PD.inputRequest\n var body = webhook.body || JSON.parse(webhook.rawBody);\n\n var incident_key = (body.message.markdown||\")\").split(\")\")[0]; /*so hacky, but resource.workItemId isn't populated on create*/\n var description = body.message.text.split(\"\\r\\n\")[0];\n var url = null;\n if(incident_key.split(\"(\").length==2) {url = incident_key.split(\"(\")[1];}\n\n var event_type = PD.Trigger;\n try {\n if(body.resource.fields[\"System.State\"].newValue == \"Resolved\") { event_type = PD.Resolve; }\n } catch (e) {}\n \n \n var normalized_event = {\n event_type: event_type,\n incident_key: incident_key,\n description: description,\n details: body.resource.fields,\n client: \"View in Team Foundation Server\",\n client_url: url\n };\n PD.emitEvent(normalized_event);\n}", "language": "javascript", "name": "Visual Studio Team Foundation Server 2015" } ] } [/block] This script takes **Github** issues and turns them into incidents: [block:html] { "html": "<span id=\"github\"></span>" } [/block] [block:code] { "codes": [ { "code": "var webhook = PD.inputRequest.body;\n\nvar normalized_event = {\n event_type: PD.Trigger,\n incident_key: webhook.issue.number,\n description: webhook.issue.title,\n details: {\n description: webhook.body\n },\n client: \"Github issues\",\n client_url: webhook.issue.url\n};\n\nif(webhook.action==\"opened\") PD.emitGenericEvents([normalized_event]);", "language": "javascript", "name": "Github issues" } ] } [/block] Some customers have started rewriting our supported integrations. For instance, here's the start of a CET that will handle **New Relic**'s generic webhooks: [block:code] { "codes": [ { "code": "var normalized_event = {\n event_type: PD.Trigger,\n incident_key: PD.inputRequest.body.incident_id,\n description: PD.inputRequest.body.policy_name+\": \"+PD.inputRequest.body.details,\n details: PD.inputRequest.body,\n client: \"New Relic\",\n client_url: PD.inputRequest.body.incident_url\n};\n​\nPD.emitGenericEvents([normalized_event]);", "language": "javascript", "name": "Simple New Relic" } ] } [/block] This is the CET that Steve demoed on our June "What's New" webinar, it takes a **Zapier** webhook triggered from **Instagram** and makes it a PagerDuty incident: [block:code] { "codes": [ { "code": "var webhook = PD.inputRequest.body;\n\nvar normalized_event = {\n event_type: PD.Trigger,\n description: 'Incoming kitten from ' + webhook.user.username,\n client: 'Instagram',\n client_url: webhook.link,\n contexts: [{\n type: 'image',\n src: webhook.images.standard_resolution.url,\n href: webhook.link,\n alt: webhook.caption.text\n }]\n};\n\nif (webhook.caption.text.indexOf('cute') > -1) {\nnormalized_event.contexts.push({\n type: 'link',\n href: 'https://broadly.vice.com/en_us/article/why-you-are-addicted-to-cute-baby-animals',\n text: '[Runbook] How to handle cuteness overload'\n });\n}\n\nPD.emitGenericEvents([normalized_event]);", "language": "javascript", "name": "Instagram - Zapier -> PagerDuty" } ] } [/block] [block:html] { "html": "<div style='height:50em;'></div>\n" } [/block]