{"componentChunkName":"component---src-templates-post-template-js","path":"/azure-setup-on-money-en","result":{"data":{"markdownRemark":{"id":"4abd56cf-6417-50c8-8c16-e1c48155bc3b","html":"<blockquote>\n<p>This page has been machine-translated from the <a href=\"/azure-setup-on-money\">original page</a>.</p>\n</blockquote>\n<p>The other day I summarized the steps for building a honeypot on Azure in <a href=\"/honeypot-setup-on-azure\">this article</a>, but when you actually operate it, the thing you worry about is cost.</p>\n<p>This time I would like to configure Azure cost alerts so that notifications are sent before the operation goes over budget.</p>\n<!-- omit in toc -->\n<h2 id=\"table-of-contents\" style=\"position:relative;\"><a href=\"#table-of-contents\" aria-label=\"table of contents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Table of Contents</h2>\n<ul>\n<li><a href=\"#three-kinds-of-cost-alerts\">Three Kinds of Cost Alerts</a></li>\n<li>\n<p><a href=\"#create-a-budget-alert\">Create a Budget Alert</a></p>\n<ul>\n<li><a href=\"#create-a-notification-action-group\">Create a Notification Action Group</a></li>\n<li><a href=\"#create-the-budget-alert\">Create the Budget Alert</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#bonus-forward-notifications-to-discord-with-azure-function\">Bonus: Forward Notifications to Discord with Azure Function</a></p>\n<ul>\n<li><a href=\"#build-the-development-environment\">Build the Development Environment</a></li>\n<li><a href=\"#deploy\">Deploy</a></li>\n<li><a href=\"#run-the-function-from-the-action-group\">Run the Function from the Action Group</a></li>\n</ul>\n</li>\n<li><a href=\"#summary\">Summary</a></li>\n</ul>\n<h2 id=\"three-kinds-of-cost-alerts\" style=\"position:relative;\"><a href=\"#three-kinds-of-cost-alerts\" aria-label=\"three kinds of cost alerts permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Three Kinds of Cost Alerts</h2>\n<p>When I looked into Azure cost alerts, it seemed that the following three types existed.</p>\n<ol>\n<li><a href=\"https://docs.microsoft.com/ja-jp/azure/cost-management-billing/costs/cost-mgt-alerts-monitor-usage-spending?WT.mc_id=Portal-Microsoft_Azure_CostManagement#budget-alerts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Budget alert</a></li>\n<li><a href=\"https://docs.microsoft.com/ja-jp/azure/cost-management-billing/costs/cost-mgt-alerts-monitor-usage-spending?WT.mc_id=Portal-Microsoft_Azure_CostManagement#credit-alerts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Credit alert</a></li>\n<li><a href=\"https://docs.microsoft.com/ja-jp/azure/cost-management-billing/costs/cost-mgt-alerts-monitor-usage-spending?WT.mc_id=Portal-Microsoft_Azure_CostManagement#department-spending-quota-alerts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Department spending quota alert</a></li>\n</ol>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/azure/cost-management-billing/costs/cost-mgt-alerts-monitor-usage-spending?WT.mc_id=Portal-Microsoft_Azure_CostManagement\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Monitor usage and spending with cost alerts in Azure Cost Management | Microsoft Docs</a></p>\n<p>A “budget alert” is an alert that occurs when the configured budget threshold is reached or exceeded.</p>\n<p>This “budget alert” supports the following two conditions.</p>\n<ul>\n<li>Cost-based</li>\n<li>Usage-based</li>\n</ul>\n<p>Both the “credit alert” and the “department spending quota alert” are alerts for corporate organizations, so this time I will use the “budget alert”.</p>\n<h2 id=\"create-a-budget-alert\" style=\"position:relative;\"><a href=\"#create-a-budget-alert\" aria-label=\"create a budget alert permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create a Budget Alert</h2>\n<p>Following the documentation below, I will configure a “budget alert” from the Azure portal.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/azure/cost-management-billing/costs/tutorial-acm-create-budgets\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Tutorial - Create and manage Azure budgets | Microsoft Docs</a></p>\n<p>Before actually creating the alert, I decided to create an action group so I can control the notification destinations.</p>\n<h3 id=\"create-a-notification-action-group\" style=\"position:relative;\"><a href=\"#create-a-notification-action-group\" aria-label=\"create a notification action group permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create a Notification Action Group</h3>\n<p>Azure action groups can manage notification settings.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/azure/azure-monitor/alerts/action-groups\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Create and manage action groups in the Azure portal - Azure Monitor | Microsoft Docs</a></p>\n<p>This time I created an action group that sends SMS, email notifications, and notifications to the Azure app.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 675px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/b7b89a2236b94726246b7d066f36df2e/23296/image-43.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 93.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAABsUlEQVQ4y6VU23KCQAzl/2fUJ8e/qo91fKgVRWFV7rBcPd2znaWIFe00M5EIyUmyJ1lrv99jZ9twHAe2em63n1gul1it3rFer1GWJSjX61XrM7H407btjdZ1jaZpbhxfAdOAaZoiyzKteZ6jKApUVQVxOmOz3cH1hE7Sr3JMrTAMEQQB4jjS7TW6ygZRKnH0E/iJ7KrrB/arvgEUwsPxeMRJCF3ZqzIE7Vpmi6bdKIrgKnDf9+F5HgJVPZOFWYkgbyDSGqe4UHaNUKr/SY1dVEOcAxVzQZIksJihTwjJMPbD6kikimtaoz/x1uVy0UQMhR9JGLOycmrMp6rajNI39JBlFcAW2bIBoriui9lshslkgvl8rnWxWGA6neJNzanxvWOZmX1VZRzHN7NH58PB0cnGSBnaVpalHbvDbExSFPLXb4/e6Tl8Ni5DgDE/y1G7vNl86MOXUmqlXVUlhLjfEgqPyba3ugOOHGMMUZYBMWtHm04EkjLvzrUPyF2nr1GC8V23y4bhZy0/uyR0y0T/jf5HBIxdErrCsjfUr15Ro9cX54wkPFr2PwOSALLWP/z/yBdXcM50i5aEDQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/b7b89a2236b94726246b7d066f36df2e/8ac56/image-43.webp 240w,\n/static/b7b89a2236b94726246b7d066f36df2e/d3be9/image-43.webp 480w,\n/static/b7b89a2236b94726246b7d066f36df2e/3bfaf/image-43.webp 675w\"\n              sizes=\"(max-width: 675px) 100vw, 675px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/b7b89a2236b94726246b7d066f36df2e/8ff5a/image-43.png 240w,\n/static/b7b89a2236b94726246b7d066f36df2e/e85cb/image-43.png 480w,\n/static/b7b89a2236b94726246b7d066f36df2e/23296/image-43.png 675w\"\n            sizes=\"(max-width: 675px) 100vw, 675px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/b7b89a2236b94726246b7d066f36df2e/23296/image-43.png\"\n            alt=\"image-43.png\"\n            title=\"image-43.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>When you create the budget alert, configure it to trigger this action group and the budget alert notification will be sent.</p>\n<p>Action groups can also be used for notifications other than budget alerts.</p>\n<p>This is also an optional setting, but you can additionally define actions to run when the action group is triggered.</p>\n<p>That means you can also perform arbitrary processing by using Function and so on.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 526px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4931463f553b1c5b1009acb2bdcc696a/2d7ab/image-44.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 90.41666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAABlklEQVQ4y6VU2Y6DMAzk/38PVtq+FVaqxBlycJQWvB7TVMBSsVUtWU6TeDx2hgZZllF8PlOSJHS5XCiJY4lfUURRFFIYhrJumoZg0zQ9fc8CetNeAT0BrbUE11pT27ZkODpnqe978aqqKM9zUhy7rlux3AVEK7gIUAD85JriVNH1OtDtdpNCAEXE+bbtJThiMAwDFUXBAFf6xDxogKplWVJd1zJ4a42wNcbIHphhH2sUds7JGVgrpSQumQtDJGB+/rIHw+W6VnKO5DRNpRjOMFcUgPeL2QaYEzZjlsvp9E33+/1PO2AJsKOWBbBjZpYZtcyiYYZgA3ePtdY1lUUudzAOxwydKMM8Hb+Rq7kbYQhJVDxHtIVWADaOo7DFSNAS7s0+LNbrvYEfNkCiSKOch4wBY+8dMa90iOSCWeFR4OM4rUAQfYE9/W1dADN5Pfdy0FvAQ4Y5/0FkWf747Jy0DravGB4CqodIoS/oTKmKmk8AwQoPg+93z94ChDTACAyNsfPzs1Tgfu3F/i9A35J3JG99+eJH9gsj+IFJkzbzlgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/4931463f553b1c5b1009acb2bdcc696a/8ac56/image-44.webp 240w,\n/static/4931463f553b1c5b1009acb2bdcc696a/d3be9/image-44.webp 480w,\n/static/4931463f553b1c5b1009acb2bdcc696a/9752a/image-44.webp 526w\"\n              sizes=\"(max-width: 526px) 100vw, 526px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/4931463f553b1c5b1009acb2bdcc696a/8ff5a/image-44.png 240w,\n/static/4931463f553b1c5b1009acb2bdcc696a/e85cb/image-44.png 480w,\n/static/4931463f553b1c5b1009acb2bdcc696a/2d7ab/image-44.png 526w\"\n            sizes=\"(max-width: 526px) 100vw, 526px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/4931463f553b1c5b1009acb2bdcc696a/2d7ab/image-44.png\"\n            alt=\"image-44.png\"\n            title=\"image-44.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<h3 id=\"create-the-budget-alert\" style=\"position:relative;\"><a href=\"#create-the-budget-alert\" aria-label=\"create the budget alert permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create the Budget Alert</h3>\n<p>Next, create a new budget alert from “Cost alerts” on the subscription page.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 580px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/0a519d71cb664b869e28372f79e0e796/b6272/image-45.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 125%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAYAAAAxFw7TAAAACXBIWXMAAAsTAAALEwEAmpwYAAACnklEQVQ4y61VaW/aQBT0r+u3SlWF0kuqqvzXfOZKlCCRFALEmMMXvrAN0zfPLDI0QJR2pdGaPWbfmze7WP1+Hzc3N+h02mi1Wri7u0NRFNhutwd4a7OiKEJZlvrjePMxqZk7d4C13WzgukvMZg7SNFU4jgPf9w82v5kwjDM82Uv0xzMEUYJMCF3XxWq1ejXlS+lbcZJgPJnA83wlcZyp9u5yidFohMVigfl8rlFT21NSmIMs/dgNbCT9Ok5tPEsYx7FGslqF+NdG0j0hUyKoH6ueiBRZlimq6EtNma7wPE97yhGGIZYiD/uqKPLRe3jAYDBAr9fDeDzGw/092q0m2u0Wms0mbm9v0e12xasd9SodsJaDqDVdQXL2SshTjdhsnPzx8xc+fPyMT40v+P7tK66urhSNRgPX19d7S72aMtNbr9cH4vpJgeEixtSLECepHFiqDIWAxTpneivPc42qGtSlWMYbjOcBBhMH/ZGDcvt3JKc8aR0vNDY6GL9gpTq5xWo+Pj7K1Zu92yp1yE2JYdu23pAgCLT8tBLtQxib+ALO85ugVbjuOG0rlQh931PfcQOtwMXPwyHmEnUgFeU1JDnHCY7Ts5yjQ0pBXuQqiVWkGUIhYqVN42bbftExY6s6WHGCBaUfuS5OIp2zNnS/RLWQk7mAbTqdYuZUzxnTYvSJ9HENOlYDM1PCUtg9Xredv9hoXPPwJqIxF1JbbizLQg/iWJome2RZWhWlkJDtlxd4QmIE5nNF4fk2UldGzkP5TbKVkDNNHso1vO9RtIvQRFX3GAk4ybFydzuMdvUxo2WF6n/IMk/+/2r6J/X76WlfAML8ab2LkAQTebKoGavLN85U7DCl8yjKSiKNMAoPX2t/Z2aSUvxLyNc50qxywB+iEI/Iq4fRmQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/0a519d71cb664b869e28372f79e0e796/8ac56/image-45.webp 240w,\n/static/0a519d71cb664b869e28372f79e0e796/d3be9/image-45.webp 480w,\n/static/0a519d71cb664b869e28372f79e0e796/4fac6/image-45.webp 580w\"\n              sizes=\"(max-width: 580px) 100vw, 580px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/0a519d71cb664b869e28372f79e0e796/8ff5a/image-45.png 240w,\n/static/0a519d71cb664b869e28372f79e0e796/e85cb/image-45.png 480w,\n/static/0a519d71cb664b869e28372f79e0e796/b6272/image-45.png 580w\"\n            sizes=\"(max-width: 580px) 100vw, 580px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/0a519d71cb664b869e28372f79e0e796/b6272/image-45.png\"\n            alt=\"image-45.png\"\n            title=\"image-45.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>For the alert conditions, you can set forecasted and actual values as percentages of the budget.</p>\n<p>This time I configured warnings like the following, including an alert when the forecasted usage exceeded 90%.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 570px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/37ca5edb9753f4d17557b95aa724b1fd/432e7/image-46.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 83.33333333333334%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB0UlEQVQ4y41Ua4/aMBD0//9Z16/oqNQPVBAS9SoCedlJICHv6Y57Sc0VpKy0yuJdj2fHXtS3tzd8326x2WywfX+HMQa0aZoevmtNVVWFcRzRdZ11176CrgFXdV2jKAo0TYNJgHOdQWfpAk6Q2deAqrIsbZsEzKsWu+CEH4dfqJvuv+JVDAmYZRlOpxMybRBeYpjiKmsaYRha15JfzXCUgr7vwdbZZitMu661MVk39nf3VM9ncqj4crEM19jfjdNLlhYwiWML6J7CW392ugv0leGcU9SobZulaBgGq+fvjw8rBe12u+EinbgtV9UNWmshk+J+v/9jmKaPCwSpBIC6kSmtbVtEUSR19cKG75d7+eRclmp+g5+IFtA9gEZwMlzqPlknSYxS9rsSqFg0dAGGJ4BkSEB3kgiYJgn47B4Az+ez3eBqSMA55ndmyDZdQK4Zox8v5egdsN/vEUmyLAsYEZqxkRGkZhSfcZpEMFmCQgA4nqzJc2PztRxUWi1HqMA/4uduB++wB+Pj0ZP4gKPnIQgC+L5v15jzmRcC1I5gJHC9lnIx+TJNKr520FWPMG/hxZWdlGEYbbu8IDpj119NC1dVP4pW4r28kHZY/9/3alr+ALPqLcAm8JNlAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/37ca5edb9753f4d17557b95aa724b1fd/8ac56/image-46.webp 240w,\n/static/37ca5edb9753f4d17557b95aa724b1fd/d3be9/image-46.webp 480w,\n/static/37ca5edb9753f4d17557b95aa724b1fd/048c8/image-46.webp 570w\"\n              sizes=\"(max-width: 570px) 100vw, 570px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/37ca5edb9753f4d17557b95aa724b1fd/8ff5a/image-46.png 240w,\n/static/37ca5edb9753f4d17557b95aa724b1fd/e85cb/image-46.png 480w,\n/static/37ca5edb9753f4d17557b95aa724b1fd/432e7/image-46.png 570w\"\n            sizes=\"(max-width: 570px) 100vw, 570px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/37ca5edb9753f4d17557b95aa724b1fd/432e7/image-46.png\"\n            alt=\"image-46.png\"\n            title=\"image-46.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>That completes the cost alert notification settings.</p>\n<p>If you get good enough with the Azure API and the like, it might even be possible to automate something like stopping all resources when an alert is sent from the action group.</p>\n<h2 id=\"bonus-forward-notifications-to-discord-with-azure-function\" style=\"position:relative;\"><a href=\"#bonus-forward-notifications-to-discord-with-azure-function\" aria-label=\"bonus forward notifications to discord with azure function permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Bonus: Forward Notifications to Discord with Azure Function</h2>\n<p>“Azure Function” (called “Function App” in the Japanese UI) is a service that can run applications in a serverless way.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/en-us/azure/azure-functions/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Azure Functions documentation | Microsoft Docs</a></p>\n<p>Create a new Function from “Function App”.</p>\n<p>I set the runtime to Python.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 675px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/f8a1e1c611fc006ffe00700b9be4ec56/23296/image-47.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 90.83333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAACYklEQVQ4y5VU227TQBD1F6d8C4g/oBKlNEFCUC5PUPUTgCQkJKlyt+PLrq/ry2FmHCemaQWMdLTr1Xj2zJljWyvbw3TlYLxRcFwfodaoquqv4Gjvm7AGgz5+fP8Gd2djPB4J/iUeu8RqEsqyPCQXRSHgM17zPN+vBsZkyI15kCHvrbXjSataK6RpSqvGbreD71P7YShQSklBPt9sNnLWjmJ/oTB0nB1m0ykWiznm8znGoxHu7u5g2za2262cNc/L5RLLxYJyF5hMJiTPWPbr9RpBENQF+TZOnM1mwiBJEkRRJGx55UQGM4/jWFYG54X7s7aOxNDBcDjEoN8XRpzMN3qed9CHX27rxO010kREiC+UnGrPkIsGpJnJsj+0ubn5isvXl+i96eGqe4Vur4uLi5cYkROIDzIakBEYKlgztXiC3BoXjmllgRtmt19u0X3Vw4d3H/Hp+rPg/dtr/Po5QawTBK6C8rTAc3xxhdW2CtuhpLUpuHRz+Lo4NSE5LE/JWllZg/YmqYlYGbXpk16r1UoEbnTiMHzJ3od5QdYo9/6syge/Epkyi8+j91xX2m0XfP7sKZ6cnaHT6eD8xflhQOyABooG4ns++darW2aG7WEcv1PAVrEY3vVcMTcP4X6IlUJ9HAoPRJKpaNV8ftwOLbYbIQ5jpEmGSNf7wpQo8yOqsta0NLUMFo9cTEuF238RDp/+RMrVyGKDLDJIowyJTk8QKzK5T++XVJB14GL3W+YIvAChIjuFyQFJdAo+D1XUtBwiaU2X6x0YOvSPXO2EXZ6QNeL8USQ6qxmeMqtOmP5P/AaSOmvFj/yEAAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/f8a1e1c611fc006ffe00700b9be4ec56/8ac56/image-47.webp 240w,\n/static/f8a1e1c611fc006ffe00700b9be4ec56/d3be9/image-47.webp 480w,\n/static/f8a1e1c611fc006ffe00700b9be4ec56/3bfaf/image-47.webp 675w\"\n              sizes=\"(max-width: 675px) 100vw, 675px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/f8a1e1c611fc006ffe00700b9be4ec56/8ff5a/image-47.png 240w,\n/static/f8a1e1c611fc006ffe00700b9be4ec56/e85cb/image-47.png 480w,\n/static/f8a1e1c611fc006ffe00700b9be4ec56/23296/image-47.png 675w\"\n            sizes=\"(max-width: 675px) 100vw, 675px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/f8a1e1c611fc006ffe00700b9be4ec56/23296/image-47.png\"\n            alt=\"image-47.png\"\n            title=\"image-47.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<h3 id=\"build-the-development-environment\" style=\"position:relative;\"><a href=\"#build-the-development-environment\" aria-label=\"build the development environment permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Build the Development Environment</h3>\n<p>Azure Function is developed from localhost by using VSCode or any editor you like.</p>\n<p>Unlike AWS Lambda, it does not look like editing from a web editor is possible.</p>\n<p>Next, run the following command on localhost (Windows) to install the Core Tools.</p>\n<div class=\"gatsby-highlight\" data-language=\"powershell\"><pre class=\"language-powershell\"><code class=\"language-powershell\">npm install <span class=\"token operator\">-</span>g azure-functions-core-tools@3 <span class=\"token operator\">--</span>unsafe-perm true</code></pre></div>\n<p>Even in an environment where Node is not installed, it can be installed by following the steps in the documentation below.</p>\n<p>Reference: <a href=\"https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=v4%2Cwindows%2Ccsharp%2Cportal%2Cbash#install-the-azure-functions-core-tools\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Work with Azure Functions Core Tools | Microsoft Docs</a></p>\n<p>Next, since I was developing in VSCode this time, I installed the following VSCode extension.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/2018b4be8fb0e8abe8aa6804e8d43882/0b533/image-48.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 112.91666666666667%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAAACXBIWXMAARlAAAEZQAGA43XUAAADkUlEQVQ4y31VS5LjRBT0HYihsSVZ1v///zVty3ID3UBATPSGCGbBgg0RBCuuwVnmAnO6JF9Z8tjdAYtnVcmqrHyZ71WtiqJEnhcoihyun8N2fNi2g93OgmXZDOsytm0bjuPAdT2Gy/HnSNMMnudjpesGDG2NL+80fHi/QRF/BdtyUTc1irJU0TQtsixDFMewXR8bTYNhGNhut5eQucTK1Dd451Z4fnnEp3/ewR2fYacDDocRTUXmeYah79F1PcrYwUOio0x8uGSzgF6Dr8z1He6qE3796xd8/PsL5B9+h5UPSOsBiUTzNZKsQBSFiMMARRohS1P4vg+dTPWZ2QVQfjaajrYOkMc2NqJXUiN+/weSH39D8vIn0m6PwKdWohv1Ex2XEF2vWa6WyXq9hkZgQ9tAM7bIs5zpptRzpwwIw5CieyqEXRAECPhOxjeAuq6rj5q65p8eYgofRZEyQRjIQpkLE/lPQmW14cZX5pxNIaAMZGEcxYqJ2pkREkQ2WgDVOzJKkuTyXtZdu6wYyi6yYJomtG2Lmkx7ulpVFeszp7sdy6bB/f29ep7BQlV3wtq4MkWVjaQszIZhUE+ZLx+pGlUfG5d3pmkS0EcU+jCvmL3RUNiU7JaqKsmyQsWCrjkWbYuiUIyXDR2PMuSd6iqD8+sCV4ABnWraDnHeIClaRFnNZ4ek7NkptQIrGeLq1tCwDRqYxfcwLI9zZvQaUKyXFtNMB9rWPod5jq1pwZl7WFwUANNNsIt6bO3wc8qLhmKKVP7xOKG6P2E8HHCajnh8PGE6jsqscRyVIcJ0t9spDcuyUFKJpjcpG7MmbTfQ3U6ZIy4PQ39+0l1xWOpSXFUSSSmxHmUTKaXb1tPZj3aAw+N3OJ0mBlmOewz7CQ+HI8EG7Pd7FVKDApgkKQ0sybJUx5s+G6NSNqiJxfOsrGqVeklH8yxGmJTwwxgenV1233GxLBK3pWMyVoZs4jP1S9nIQFKR3fL5A0mvFmf5TnQTQ4TJArzU6tLXouvN4aDNtdi2jeqWnGegNx8AMbtIji7R6nrhAryAX1JeABMCTscaOQ/VjG0l7aX6mc9Lf4fRG9A3vbzsJNQPhz1TrOnsA1KmnRFwLFOVdsZ7J6XG1qzja8CbA3bp575nyXQtXn7+Bk/PP+DbwwN+GqT9WIN1i+enJ6Wn/qrd/hNQatDnXRF4zpwyLyXbVbegx5Nabkgp5P9j+C+9UJ5/fN6zygAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/2018b4be8fb0e8abe8aa6804e8d43882/8ac56/image-48.webp 240w,\n/static/2018b4be8fb0e8abe8aa6804e8d43882/d3be9/image-48.webp 480w,\n/static/2018b4be8fb0e8abe8aa6804e8d43882/b0a15/image-48.webp 500w\"\n              sizes=\"(max-width: 500px) 100vw, 500px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/2018b4be8fb0e8abe8aa6804e8d43882/8ff5a/image-48.png 240w,\n/static/2018b4be8fb0e8abe8aa6804e8d43882/e85cb/image-48.png 480w,\n/static/2018b4be8fb0e8abe8aa6804e8d43882/0b533/image-48.png 500w\"\n            sizes=\"(max-width: 500px) 100vw, 500px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/2018b4be8fb0e8abe8aa6804e8d43882/0b533/image-48.png\"\n            alt=\"image-48.png\"\n            title=\"image-48.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Once the extension has been installed, select <code class=\"language-text\">Signin to Azure</code> and log in to Azure from VSCode.</p>\n<p>Then your subscription will appear in VSCode, and the Function you created earlier will also appear.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 378px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/7726f6ca0421e76c00e3643b84f6fbc3/f0991/image-49.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 75.83333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACGUlEQVQ4y5VU2XLaQBDUG+dbyuENUhbikkD3sSsJHSDOSiWfwV/w6Z2ZjUmZGLvsh67ZlWZ7u1tT0oQQyLIMlmVhsbDw/ekbOu02Op0uWq02WrRuK3ReKr2jdbfbRa/bQ6/XQ7/fp/4OBoMBNCarqgq+HyKKMohkjeMxR1nVaJoTdruzqnW1w7Y54nz+jcPhJ+IoRRAIhKGkc7yWaq/5vg+G6zJCahAoyhz1psFmsyfCk6p5ViDNSqzXNbK8VL22HcBxAqq+qgylkGGaFvTxGLPZnOzbSOIEfhiR4oSIMjrkYDgcYjT6QXWE52cdY+rX9XtozW6Puq6I0IQxmWI+N+G4LtkIkMoUVb1BsSZ1aYokkaR2S/1bOLarCAxjcgfN9zy4jkOqlurBYmHCpr2UEmEQEomgSAIEBHbBfY7j0cULUmi8JZR0c1GWd4TLlU1ZFXSRS5lGlJdHgYfqPVtl3NQx6Wti7XQ+4XjYvyK0YNKaCcMggOdR4JQf1xvB7fBDhVEcU16hmkN+MGfLlI8UKYSQKIoCMs1VjalXKfqP5N4yZSVTieXyRSF9lBV9lCTjuYyR5zl8sssKOQLDMB4q+0e43TY0rCciXP1VOJ3BTdcof9UQsVBjc8tNjcoHdhWhR0OdJLFSeAtYQZ+o4B8d/FAhW2LbPBL3jcanCN4QXq9XXC4XTMnqePx+42dJNf4xsEoem68oeQ9/ACTZx6wH4KjaAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/7726f6ca0421e76c00e3643b84f6fbc3/8ac56/image-49.webp 240w,\n/static/7726f6ca0421e76c00e3643b84f6fbc3/d6ea2/image-49.webp 378w\"\n              sizes=\"(max-width: 378px) 100vw, 378px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/7726f6ca0421e76c00e3643b84f6fbc3/8ff5a/image-49.png 240w,\n/static/7726f6ca0421e76c00e3643b84f6fbc3/f0991/image-49.png 378w\"\n            sizes=\"(max-width: 378px) 100vw, 378px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/7726f6ca0421e76c00e3643b84f6fbc3/f0991/image-49.png\"\n            alt=\"image-49.png\"\n            title=\"image-49.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Next, create a local Function from the [Create Function] button in VSCode.</p>\n<p>I chose the trigger “HTTP Trigger”.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 443px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/23e2ec3418070467e8c2c9bb87b3b991/a120c/image-50.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 27.916666666666668%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsTAAALEwEAmpwYAAABLElEQVQY01WQXU6DQBSF2YUPNrXAMPy1MED8aQXb8k9Nao3pHnzUF5fgNtyM+zoeCI3tw5c5k3vn3DNXi6IESikIYcGy5MBJC2JTe2RKfU1kXztx1m/bDhzHhRbHCcIwZENf/G+SRCdLU+Bzpg+8GeZgbI4mYjTuTyntAa1tO/Q0TYO6rNE2O+Tb/CKBR+55fzcMfOn6MMwlzlg/R6tpVJQlqopmbYuX/R5d94woijmZSfkVi5MN6eCK+igEvqczfDDxLdPrZ2Z9Uq2uKpRFzmQtNusM6eMKWZohXARMKWBL7nFMI6kDPvpxTPxKHZs4hjdfIPDn8D0fiqvTit0rtt0ezeGIu6zAxHRxI+fQ3RCmpy4QvsLEDpAWKQ7rFCv2J2mOZPkE9bDGalvjD2SGuwGlhNAbAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/23e2ec3418070467e8c2c9bb87b3b991/8ac56/image-50.webp 240w,\n/static/23e2ec3418070467e8c2c9bb87b3b991/23445/image-50.webp 443w\"\n              sizes=\"(max-width: 443px) 100vw, 443px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/23e2ec3418070467e8c2c9bb87b3b991/8ff5a/image-50.png 240w,\n/static/23e2ec3418070467e8c2c9bb87b3b991/a120c/image-50.png 443w\"\n            sizes=\"(max-width: 443px) 100vw, 443px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/23e2ec3418070467e8c2c9bb87b3b991/a120c/image-50.png\"\n            alt=\"image-50.png\"\n            title=\"image-50.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Looking at the Function App created locally, you can see that a simple template has been generated in a file named <code class=\"language-text\">__init__.py</code>.</p>\n<p>So I decided to tweak the template’s <code class=\"language-text\">main</code> function a little.</p>\n<p>What it does is simple: when the Function is called, it just sends a message to Discord’s webhook by using <code class=\"language-text\">urllib.request</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">import</span> json\n<span class=\"token keyword\">import</span> logging\n<span class=\"token keyword\">from</span> urllib <span class=\"token keyword\">import</span> request<span class=\"token punctuation\">,</span> parse\n\n<span class=\"token keyword\">import</span> azure<span class=\"token punctuation\">.</span>functions <span class=\"token keyword\">as</span> func\n\nDISCORDWEBHOOK <span class=\"token operator\">=</span> <span class=\"token string\">\"&lt;Webhook URL>\"</span>\ndata <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"content\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Azure Cost Alert\"</span>\n<span class=\"token punctuation\">}</span>\nheaders <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"User-Agent\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"curl/7.64.1\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"Content-Type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"application/json\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">:</span> func<span class=\"token punctuation\">.</span>HttpRequest<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> func<span class=\"token punctuation\">.</span>HttpResponse<span class=\"token punctuation\">:</span>\n    logging<span class=\"token punctuation\">.</span>info<span class=\"token punctuation\">(</span><span class=\"token string\">'Python HTTP trigger function processed a request.'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token comment\"># Post to Discord</span>\n    parse<span class=\"token punctuation\">.</span>urlencode<span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    req <span class=\"token operator\">=</span> request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>\n        url <span class=\"token operator\">=</span> DISCORDWEBHOOK<span class=\"token punctuation\">,</span>\n        data<span class=\"token operator\">=</span>json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        headers<span class=\"token operator\">=</span>headers<span class=\"token punctuation\">,</span>\n        method<span class=\"token operator\">=</span><span class=\"token string\">\"POST\"</span>\n    <span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">with</span> request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> response<span class=\"token punctuation\">:</span>\n        response_body <span class=\"token operator\">=</span> response<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> func<span class=\"token punctuation\">.</span>HttpResponse<span class=\"token punctuation\">(</span>response_body<span class=\"token punctuation\">)</span></code></pre></div>\n<p>One slightly tricky point was that Discord’s webhook seemed to blacklist <code class=\"language-text\">urllib</code> as a UA, so I changed the UA to <code class=\"language-text\">curl</code>.</p>\n<h3 id=\"deploy\" style=\"position:relative;\"><a href=\"#deploy\" aria-label=\"deploy permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Deploy</h3>\n<p>Once the code is finished, you can deploy the Function you created to any Function App from the <code class=\"language-text\">Deploy to Function App</code> button in VSCode.</p>\n<p>After deployment completes, you can confirm that the locally created Function has been added to the Azure Function App.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/d051fcf3c57b2a0fd5c19f9e42b759b5/0b533/image-51.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 60.83333333333334%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAARlAAAEZQAGA43XUAAABjklEQVQoz51Ta2+kMAzk///D+3BVd7WEQgl5P3lM7WxBla6q1LMYJQp4Mh6bzseCvhe43+8QQmAcR9rfMNF6u72i1oJ/4jjo+R6dcaERLYtECAHee8QYUeqKEDPqtiOXgpwL9p2T8GN0xmgiU9i2jRL2hkIEtSQ4KaDVDHF/wevfP9ByhFXvMMuE5BQiIXt9Ya8B3WQcES5IKTXJHIvSCEbicAOSnRvMLBD0BK/GtrdygFve2tkJFEcK/QpFhPM8k1/1SSgllDbwMcFY2xRvpHxd16sSXhnrul3nlWzq9GKbf845bPSiEdIFxhhkUl1Luaz4aslXi7gyFsPoJCkZhgGWlPBHHEqppvJB3ZfKoOSERI3iC4J3GETf1pwinQe6NGOeRoxvA7qUfCuLO3t6yIRsg7GOSrct+YR3FkZrxOCvM95baq6zhpoyTa2E1lmSfBw7+fneRuh/ohv6G0T/LMFohUAKRP+4CI8fhvjbwdbuOTas8AxJ/vGAn4S/UmhpNFgNN+RMbn/K5wW/JfwAP/6l4+w7uwAAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/d051fcf3c57b2a0fd5c19f9e42b759b5/8ac56/image-51.webp 240w,\n/static/d051fcf3c57b2a0fd5c19f9e42b759b5/d3be9/image-51.webp 480w,\n/static/d051fcf3c57b2a0fd5c19f9e42b759b5/b0a15/image-51.webp 500w\"\n              sizes=\"(max-width: 500px) 100vw, 500px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/d051fcf3c57b2a0fd5c19f9e42b759b5/8ff5a/image-51.png 240w,\n/static/d051fcf3c57b2a0fd5c19f9e42b759b5/e85cb/image-51.png 480w,\n/static/d051fcf3c57b2a0fd5c19f9e42b759b5/0b533/image-51.png 500w\"\n            sizes=\"(max-width: 500px) 100vw, 500px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/d051fcf3c57b2a0fd5c19f9e42b759b5/0b533/image-51.png\"\n            alt=\"image-51.png\"\n            title=\"image-51.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>This Function runs simply by sending an HTTP request to its trigger URL.</p>\n<p>When I opened the Function and hit the URL obtained from “Get function URL”, the message was forwarded to Discord.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/14d3c79638c3395035ca5b325d4dd011/0b533/image-52.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 33.75%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAARlAAAEZQAGA43XUAAABUklEQVQoz3WRy07DMBBF84GsWPAJ5dGvogUkCl/AtrRILLpAgooFD1FK28RJGydO7LwOrgtSi8RIRx5fj8ajO15RFOSmRMqYsgKd3rCc7BFP9kmmB2TqhTCUloCyLIGGptmirjf83L1cvLESM8TXK+FsiooeCCdniI8L/Pdzovmz1T8Ipq9oKcBIGh07KBKo1Aar1/kKL/Kn1KXBZCmL2SfBImAxX5HEhsoOVBpt3zVVoWls3SbP3ZnEEZFYEAZzciXt8CXeMraJjUyl9HqXXF/16HRPGY8fnd6wG3meo1SGNob+7S3dbpfTToenp7F791SaEKWa2VIxEQlSWyObmqqqWPtbW39cY+sPzd/2u+E8FCIglBn3D88cnbRpHR7TbrcdrVaL0Wjkitcf7CzjHzxjR69tcZpI7oZDhoMBA8vQ5v1+H9/3XcN6a5O/rLVt1to3NlAMF2JeCzcAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/14d3c79638c3395035ca5b325d4dd011/8ac56/image-52.webp 240w,\n/static/14d3c79638c3395035ca5b325d4dd011/d3be9/image-52.webp 480w,\n/static/14d3c79638c3395035ca5b325d4dd011/b0a15/image-52.webp 500w\"\n              sizes=\"(max-width: 500px) 100vw, 500px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/14d3c79638c3395035ca5b325d4dd011/8ff5a/image-52.png 240w,\n/static/14d3c79638c3395035ca5b325d4dd011/e85cb/image-52.png 480w,\n/static/14d3c79638c3395035ca5b325d4dd011/0b533/image-52.png 500w\"\n            sizes=\"(max-width: 500px) 100vw, 500px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/14d3c79638c3395035ca5b325d4dd011/0b533/image-52.png\"\n            alt=\"image-52.png\"\n            title=\"image-52.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>With that, I had created a simple Function.</p>\n<h3 id=\"run-the-function-from-the-action-group\" style=\"position:relative;\"><a href=\"#run-the-function-from-the-action-group\" aria-label=\"run the function from the action group permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Run the Function from the Action Group</h3>\n<p>Finally, I edited the “Action” settings so that the Function can be executed from the action group I created earlier.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/a9a0b67c5a29fedeaa2f68eebc30d517/0b533/image-53.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 61.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAARlAAAEZQAGA43XUAAAB20lEQVQoz41TTW/TQBD1j4djkRANrRAHDhQpIAIqXMp/4FCUSpU4NSHQxl7Hu2vvp+3XmXXcJO2FkZ5md7w78+bNOiuKAjeLBaTS6LoObduiJd91bVpzrO97sLEf1957lGWJpmlgjIW1lg8ga+oaPgRYH+iDgdYaxnlaN2nPFzjxmIwLsOVig7fvp3h3NsWHT1/x8ct3/BEamZQSzjmM1tMFLpLQDPD0/TGYERdn4454b1wghsSgpstjK8xGURFOZK2BNYzmAcw8eId8vcZsNsO383Msl8vEPJAMmVIq6TG2EmNEUeSoqbrbMnHWHnhmyOwuL3/h+moOpWTqrI3EkBPsC87g2DiQEaN+CbRmlkYK5NJAVBKltqgMJczz/EBDtkBDemzcxVB42Evj8WP+D9Ofd7itTIrHjqYshAA/HdaS2+fJVlWVkqYnRGDGfI5jg9Y9RB3wea6wruNBIWrZEX3SxzUDLE3VmxQLYYe29aQTXe5Jip58Fx/Yd3vvNKMnRwH8t41HeYZxq+f+DLJi9RKL38/gqtfw6gS2miBfvSB/QnuKyR2iPkX+9wi3q+eI7mKbaPcnpZZr8QZqPYEtJ/CUrC5eobo7RiMmcJun0OUp9OYYwVw8+R3Z7gGnF5dZfmohOwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/a9a0b67c5a29fedeaa2f68eebc30d517/8ac56/image-53.webp 240w,\n/static/a9a0b67c5a29fedeaa2f68eebc30d517/d3be9/image-53.webp 480w,\n/static/a9a0b67c5a29fedeaa2f68eebc30d517/b0a15/image-53.webp 500w\"\n              sizes=\"(max-width: 500px) 100vw, 500px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/a9a0b67c5a29fedeaa2f68eebc30d517/8ff5a/image-53.png 240w,\n/static/a9a0b67c5a29fedeaa2f68eebc30d517/e85cb/image-53.png 480w,\n/static/a9a0b67c5a29fedeaa2f68eebc30d517/0b533/image-53.png 500w\"\n            sizes=\"(max-width: 500px) 100vw, 500px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/a9a0b67c5a29fedeaa2f68eebc30d517/0b533/image-53.png\"\n            alt=\"image-53.png\"\n            title=\"image-53.png\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Now, when a cost alert occurs and the action group sends notifications, Discord is notified in addition to SMS and email.</p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>I configured cost alerts in Azure and also set up notifications to Discord through a Function.</p>\n<p>Action groups in particular seem like they could handle all kinds of automation once you get comfortable with them, which is exciting.</p>","fields":{"slug":"/azure-setup-on-money-en","tagSlugs":["/tag/security-en/","/tag/azure-en/","/tag/備忘録/","/tag/english/"]},"frontmatter":{"date":"2022-02-12","description":"","tags":["Security (en)","Azure (en)","備忘録","English"],"title":"Notes on Setting Up Cost Alerts to Use Azure Safely","socialImage":{"publicURL":"/static/40d9f783286082e7cbb69c0b4caa1c73/azure-setup-on-money.png"}}}},"pageContext":{"slug":"/azure-setup-on-money-en"}},"staticQueryHashes":["251939775","401334301","825871152"]}