Streaming Logs Externally
External log streaming
The external log streaming feature is available to customers on specific pricing plans. Refer to your pricing plan or contract, or contact the Prismatic support team to learn more.
You can configure Prismatic logs to stream to an external logging service (like DataDog or New Relic), or to your own proprietary logging system. Logging services generally have robust APIs that accept HTTP POST requests with JSON payloads containing log messages. All you need to configure in Prismatic is where to send the logs, what format the log data should take, and specify any headers that your logging service requires (like an authorization header or API key).
To configure log streaming to an external service, open Settings on the left-hand sidebar, and then select the Log Streams tab. Create a new log stream by clicking + Log stream.
Enter the URL the logs should be sent to, and add any headers that your logging service requires (many require an API key or authorization header).
Next, create a log message template. This template defines the shape of the message that will be sent to your logging service. You can add placeholders for the log message, as well as information about the instance, customer, flow and step that generated the message.
Your template can include the following placeholders, which are substituted when a message is sent to the external logging system:
Placeholder | Description | Example |
---|---|---|
{{ timestamp }} | Timestamp of the message in milliseconds since epoch | 1637087683123 |
{{ timestamp_s }} | Timestamp of the message in seconds since epoch | 1637087683 |
{{ timestamp_ns }} | Timestamp of the message in nanoseconds since epoch | 1637087683123000000 |
{{ timestamp_iso }} | Timestamp of the message in ISO format | "2021-11-16T18:34:43.123Z" |
{{ message }} | The full message body | "This is a test" |
{{ severity }} | Name of the log level (debug, info, warn, error, metric) | "warn" |
{{ severityNumber }} | The Syslog severity level | 4 |
{{ instanceId }} | The global ID that corresponds to the instance of the integration | "SW5zdEXAMPLE" |
{{ instanceName }} | Name of the instance being executed | "Update Inventory" |
{{ flowConfigId }} | The global ID of the instance's configured flow | "SW5zdEXAMPLE" |
{{ integrationId }} | The global ID of the version of the integration that is deployed | "SW5zdEXAMPLE" |
{{ integrationName }} | Name of the integration being executed | "Update Inventory" |
{{ flowId }} | The global ID of the flow of the deployed integration | "SW5zdEXAMPLE" |
{{ flowName }} | Name of the integration flow being executed | "Remove inventory after order fulfillment" |
{{ stepName }} | Name of the step being executed, if available | "Loop over order items" |
{{ isTestExecution }} | Is this log from a test in the integration designer? | true |
{{ executionId }} | The global id that corresponds to the execution | "SW5zdEXAMPLE" |
{{ customerExternalId }} | The external ID assigned to a customer | "abc-123" |
{{ customerName }} | The name of the customer associated with the instance | "Acme Corp" |
{{ executionErrorStepName }} | Name of the step that resulted in an execution error | "Loop over order items" |
{{ durationMS }} | Duration in milliseconds of the associated step or overall execution | "1000" |
{{ succeeded }} | Whether the associated step or execution succeeded | "true" |
{{ errorMessage }} | Error message for the associated step or execution | "This is an error" |
{{ retryAttemptNumber }} | The number of retry attempts of the associated step or execution | "0" |
{{ retryForExecutionId }} | The global id associated with the original execution in the case of execution retry | "SW5zdEXAMPLE" |
This template works well for many logging platforms, but may need to be modified to fit your needs:
Default message template
{
"message": {{ message }},
"timestamp": {{ timestamp }},
"severity": {{ severity }},
"service": "Prismatic",
"instance": {{ instanceName }},
"customer": {{ customerExternalId }},
"integration": {{ integrationName }},
"isTestExecution": {{ isTestExecution }},
"flow": {{ flowName }},
"step": {{ stepName }},
"executionid": {{ executionId }},
"instanceId": {{ instanceId }},
"flowConfigId": {{ flowConfigId }},
"integrationId": {{ integrationId }},
"flowId": {{ flowId }},
"executionErrorStepName": {{ executionErrorStepName }},
"duration": {{ durationMS }},
"succeeded": {{ succeeded }},
"errorMessage": {{ errorMessage }},
"retryAttempt": {{ retryAttemptNumber }},
"retryForExecutionId": {{ retryForExecutionId }}
}
Testing log streaming
Once you have saved it, you can test your external logging configuration by clicking the Test payload button on the top right of a log stream screen. This will send a test log message to your external logging system, substituting test values like "Test message" and "Test integration" into your template.
Note: If your external logging provider uses CORS to prohibit logs from being sent directly from a web browser, you may not be able to use the Test payload button. You may see a CORS error in your web browser's developer console. In that case, save your configuration and run a test of any integration - logs from your execution should flow to your external logging provider.
Logging metrics to an external service
In addition to log lines, you can use context.logger
to write out objects containing metrics that you wish to send to an external streaming service.
For example, a code component can contain a line like this:
logger.metric({
inventoryItem: {
id: "123",
price: 10.55,
quantity: 3,
},
});
Your external streaming configuration can then extract attributes from the object passed to metric()
.
For example, your configuration could read:
{
"message": {{ message }},
"timestamp": {{ timestamp }},
"severity": {{ severity }},
"itemId": {{ inventoryItem.id }},
"itemPrice": {{ inventoryItem.price }},
"itemQuantity": {{ inventoryItem.quantity }}
}
Any time a metric line that contains inventoryItem.id
, etc. is encountered, those additional attributes will be added to the payload that is sent to the logging system.
Messages that don't contain inventoryItem.id
simply won't pass an itemId
to your logging service.
When logger.metric()
is called, {{ message }}
is the stringified JSON version of the object, and {{ level }}
is set to 99
.