System Webhooks

Appmixer Engine Events.

Component Errors

Components might throw exceptions. Such exceptions/errors are logged and users can see them in the Insights. However, you might want to implement your custom logic or notification system for when this occurs. You may want to notify your users or handle/log the errors in a totally custom way.

If you want to listen for component errors you can set the WEBHOOK_FLOW_COMPONENT_ERROR environment variable to a URL that the Appmixer engine will send an HTTP POST request to whenever an error occurs. It can you any external (but accessible) URL or you can even create a flow in Appmixer and point this URL to a Webhook component to handle these errors using Appmixer itself (e.g. by sending an email, Slack notification, ...).

Set the WEBHOOK_FLOW_COMPONENT_ERROR variable in the docker-compose.yml file:

  engine:
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      - mongodb
      - rabbitmq
      - elasticsearch
      - redis
    environment:
      # this variable has to point to your Webhook
      - WEBHOOK_FLOW_COMPONENT_ERROR=https://your.example.com/error-handling-ur

Example of an error POSTed to your URL (a validation error in this case):

{
    "err": {
        "message": "Validation error on ports: in",
        "error": {
            "in": [
                [
                    {
                        "keyword": "format",
                        "dataPath": ".to",
                        "schemaPath": "#/properties/to/format",
                        "params": {
                            "format": "email"
                        },
                        "message": "should match format \"email\""
                    }
                ]
            ]
        },
        "code": "GRID_ERR_VAL_PORTS",
        "name": "ValidationFlowError",
        "stack": "ValidationFlowError: Validation error on ports: in\n    at MessagesProcessor.process (/Users/martinkrcmar/Programming/client/appmixer/appmixer-core/engine/src/context/MessagesProcessor.js:67:19)\n    at Context.prepare (/Users/martinkrcmar/Programming/client/appmixer/appmixer-core/engine/src/context/Context.js:68:31)\n    at ContextHandler.createContext (/Users/martinkrcmar/Programming/client/appmixer/appmixer-core/engine/src/context/ContextHandler.js:60:17)\n    at async InputQueue.consume (/Users/martinkrcmar/Programming/client/appmixer/appmixer-core/engine/src/InputQueue.js:151:23)\n    at async InputQueue.onMessage (/Users/martinkrcmar/Programming/client/appmixer/appmixer-core/engine/src/AMQPClient.js:378:20)"
    },
    "type": "component",
    "flowId": "32f605b2-8fbe-4f68-9db9-ce182b35c159",
    "flowName": "New flow",
    "userId": "5f804b96ea48ec47a8c444a7",
    "componentId": "0bb33e42-fbc4-464e-98f1-459f1ff626ac",
    "componentType": "appmixer.utils.email.SendEmail",
    "inputMessages": {
        "in": [
            {
                "properties": {
                    "correlationId": "339bc448-a806-4e61-8d38-4211fcedaf12",
                    "gridInstanceId": null,
                    "contentType": "application/json",
                    "contentEncoding": "utf8",
                    "sender": {
                        "componentId": "e8c581b4-9985-4f2c-bf30-895bf1d5541b",
                        "type": "appmixer.utils.controls.OnStart",
                        "outputPort": "out"
                    },
                    "destination": {
                        "componentId": "0bb33e42-fbc4-464e-98f1-459f1ff626ac",
                        "inputPort": "in"
                    },
                    "correlationInPort": null,
                    "componentHeaders": {},
                    "flowId": "32f605b2-8fbe-4f68-9db9-ce182b35c159",
                    "messageId": "47293e2c-4e33-4558-8805-386de392ef04",
                    "flowRunId": 1607683798995
                },
                "content": {
                    "to": "2020-12-11T10:49:59.050Z"
                },
                "scope": {
                    "e8c581b4-9985-4f2c-bf30-895bf1d5541b": {
                        "out": {
                            "started": "2020-12-11T10:49:59.050Z"
                        }
                    }
                },
                "originalContent": {
                    "started": "2020-12-11T10:49:59.050Z"
                }
            }
        ]
    },
    "accessTokenId": null
}

This error was triggered in a sample flow that looks like this:

The email address in the "To" configuration field of the SendEmail component points to a variable from the OnStart component. Its value is dynamic, it is only known during runtime. Therefore the user is allowed to start such a flow, but it will fail at runtime. Start time variable contains a date string, but the SendEmail address requires a valid email address in the To input field. The error will be logged and seen in the log viewer.

Consider the flow is configured correctly this time and the email address is valid. But there is a network error and Appmixer cannot send the email.

This error will be logged and the user will be able to see it in the log viewer or in the Insights. And the JSON representing this error will look like this:

{
    "err": {
        "stack": "Error: getaddrinfo ENOTFOUND mandrillapp.com\n    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:66:26)",
        "message": "getaddrinfo ENOTFOUND mandrillapp.com",
        "errno": "ENOTFOUND",
        "code": "ENOTFOUND",
        "syscall": "getaddrinfo",
        "hostname": "mandrillapp.com",
        "name": "Error"
    },
    "type": "component",
    "flowId": "0ab287ef-7bd6-4cc3-b53b-c916c857cbe7",
    "flowName": "Invalid email test",
    "userId": "5fd744d5e9ed7d0011ca35f9",
    "componentId": "cb3f4ff5-7b6e-4d24-b7a8-2115c8254baa",
    "componentType": "appmixer.utils.email.SendEmail",
    "inputMessages": {
        "in": [
            {
                "properties": {
                    "correlationId": "254ad628-f9c1-4483-81ed-33a22ac3ddc6",
                    "gridInstanceId": null,
                    "contentType": "application/json",
                    "contentEncoding": "utf8",
                    "sender": {
                        "componentId": "bcbeda1d-9036-45af-a25d-a57cf06e3f90",
                        "type": "appmixer.utils.controls.OnStart",
                        "outputPort": "out"
                    },
                    "destination": {
                        "componentId": "cb3f4ff5-7b6e-4d24-b7a8-2115c8254baa",
                        "inputPort": "in"
                    },
                    "correlationInPort": null,
                    "componentHeaders": {},
                    "flowId": "0ab287ef-7bd6-4cc3-b53b-c916c857cbe7",
                    "messageId": "33b9fcbf-b326-4eb4-bba6-cf34979f4ba2",
                    "flowRunId": 1607944841843,
                    "quotaId": "qs-4882d03d-65e1-44dc-983e-d2a33071779d"
                },
                "content": {
                    "to": [
                        {
                            "email": "martin@client.io",
                            "type": "to"
                        }
                    ],
                    "from_email": "no-reply@appmixer.com"
                },
                "scope": {
                    "bcbeda1d-9036-45af-a25d-a57cf06e3f90": {
                        "out": {
                            "started": "2020-12-14T11:20:41.858Z"
                        }
                    }
                },
                "originalContent": {
                    "started": "2020-12-14T11:20:41.858Z"
                }
            }
        ]
    },
    "accessTokenId": null
}

Quota Limit Errors

If you have defined quota limits for the component and the limit has been reached then a Quota Error is posted to the error notification webhook. You can read more about Quotas and Limits here. Below is the example of the posted quota error which is raised when the weather API request quota limit has been reached. The type property will contain quota value. Appmixer will try to process such a message again. But too many of these notifications may indicate, that some flows are generating too many messages.

Single quota error does not necessarily mean something is wrong. Let's say a flow is writing rows into a Google Spreadsheet. And the flow is about to write 200 rows. There is a Google quota, a maximum of 60 requests at the same time. After writing 60 rows, the component will reach the quota limit and generate one of these notifications. But after some time, the quota will be available again and the component will write the remaining 140 rows.

{
    "err": {
        "message": "Ran out of quota for appmixer:utils:weather",
        "error":429,
        "data":429,
        "name":"QuotaError",
        "stack":"QuotaError: Ran out of quota for appmixer:utils:weather\\n    at Request._callback (/Driver.js:67:31)\"
    },
    "type": "quota",
    "flowId": "b7db896e-0e5c-4ee1-9cb3-1099c9f43b62",
    "flowName": "Daily Rainy Day Alert",
    "userId": "60ef4fd533d6143ba09c400f",
    "componentId": "13ad74e3-3354-463c-bf30-ea6e0c157ad8",
    "componentType": "appmixer.utils.weather.GetCurrentWeather",
    "inputMessages": {
        "location": [
            {
                "properties": {
                    "correlationId": '4dc33f4c-dbd0-4e97-ab05-381d785851f3',
                    "gridInstanceId": null,
        ...
            }
        ]
    }
}

Forgot Password

Appmixer engine has an API to reset the forgotten passwords. The Forgot Password webhook is triggered whenever a user in the system requests for forgot password API. You can configure a webhook by setting the environment variable WEBHOOK_USER_FORGOT_PASSWORD to URL where the Appmixer engine will submit POST payload as follows.

// WEBHOOK_USER_FORGOT_PASSWORD = 'http://hosted-url.com/events/forgot-password';

{
  'code': 'unique code generated for identifying forgot password request',
  'email': 'email address of user requesting for forgot password',
  'userId': 'USER id of user',
  'created': 'Date when a user requested for forgot password',
  'link': 'Link to access forgot password page on frontend'
}

If forgot password webhook is configured as explained above, the Appmixer engine will not send the email to the user and trigger the webhook instead.

Last updated