<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sameer Jejurkar</title>
    <description>The latest articles on DEV Community by Sameer Jejurkar (@sjejurkar).</description>
    <link>https://dev.to/sjejurkar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F822015%2F92c56b55-cb75-432d-a135-0105c9713eea.png</url>
      <title>DEV Community: Sameer Jejurkar</title>
      <link>https://dev.to/sjejurkar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sjejurkar"/>
    <language>en</language>
    <item>
      <title>Generative AI: A glossary of terms</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sat, 09 Dec 2023 13:28:32 +0000</pubDate>
      <link>https://dev.to/sjejurkar/generative-ai-a-glossary-of-terms-1c0k</link>
      <guid>https://dev.to/sjejurkar/generative-ai-a-glossary-of-terms-1c0k</guid>
      <description>&lt;p&gt;ChatGPT captured the world's imagination as soon as it was launched on Nov 30, 2022. Within a couple of months, it became the fastest-growing application ever, hitting over 100 million users. With ChatGPT, previously little-known terms like Generative AI, GPT, LLM etc. came to the fore. In this article, we will try to understand what these mean in relatively simple language. Please note that this is in no way meant to be exhaustive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generative AI
&lt;/h3&gt;

&lt;p&gt;Generative AI refers to machine learning algorithms (ML models) that can create (hence &lt;em&gt;generative&lt;/em&gt;) content such as text, images and even music like a real person. These are a major advancement over traditional ML models. Until recently, ML models were limited in what they could do. Traditional models are focused on specific areas such as data analysis, forecasting, image recognition, voice-to-text conversion etc. These models are trained using a structured and labeled data set. In contrast, GenAI models are trained using massive amounts of unstructured data and they are not trained with any specific focus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Foundation Models
&lt;/h3&gt;

&lt;p&gt;A foundation model is a large-scale model that serves as a base for various applications. These models are trained on diverse and extensive datasets, enabling them to acquire a wide range of skills and knowledge. These models are foundation in the sense that they provide a broad capability base on which specialized functionalities can be built. They can be adapted or "fine-tuned" for specific tasks, making them incredibly efficient for various uses. Foundation Models excel in understanding complex patterns and making predictions, which can be applied in fields like natural language processing, image recognition, and beyond. &lt;a href="https://openai.com/gpt-4"&gt;GPT-4&lt;/a&gt; and &lt;a href="https://openai.com/dall-e-2"&gt;DALL-E&lt;/a&gt; from OpenAI, &lt;a href="https://www.anthropic.com/index/introducing-claude"&gt;Claude&lt;/a&gt; from Anthropic, and &lt;a href="https://ai.meta.com/llama/"&gt;Llama&lt;/a&gt; from Meta are some examples of foundation models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Large Language Models
&lt;/h3&gt;

&lt;p&gt;Large Language Models (LLMs) are a type of Foundation Model specifically designed for understanding and generating human language. They are trained on vast quantities of text data and can generate coherent, contextually relevant text based on input prompts. These models can do things like answer questions, write stories, or even translate languages. &lt;a href="https://openai.com/gpt-4"&gt;GPT-4&lt;/a&gt; from OpenAI, &lt;a href="https://www.anthropic.com/index/introducing-claude"&gt;Claude&lt;/a&gt; from Anthropic, and &lt;a href="https://ai.meta.com/llama/"&gt;Llama&lt;/a&gt; from Meta are some examples of LLMs.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPT: Generative Pre-trained Transformers
&lt;/h3&gt;

&lt;p&gt;The "GPT" in ChatGPT stands for Generative Pre-Trained Transformers. GPT is a specific series of Large Language Models (LLMs) developed by OpenAI, known for its advanced text generation capabilities. All GPT models are LLMs but not all LLMs are GPT models. ChatGPT is an interactive chat application built on top of a GPT model (currently GPT 3.5 and GPT 4).&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompt Engineering
&lt;/h3&gt;

&lt;p&gt;Prompt Engineering is the process of composing specific instructions for (i.e. prompting) Generative AI tools to produce the desired output. It involves using precise and clear language to guide the AI tool in producing the desired output. This is often an iterative process involving refining the instructions (prompt) until you get the expected output. Good prompts can significantly improve the possibility of getting the most accurate and relevant responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Training and Fine-Tuning
&lt;/h3&gt;

&lt;p&gt;Training refers to the process of feeding a model large amounts of data so it can learn to perform a task. This is the initial training of the model and is very resource-intensive. Fine-tuning, on the other hand, involves adjusting a pre-trained model on a smaller, task-specific dataset to enhance its performance in that specific area.&lt;/p&gt;

&lt;h3&gt;
  
  
  Neural Networks
&lt;/h3&gt;

&lt;p&gt;While the term "Neural Networks" doesn't come up as often as some of the other terms, no discussion about Generative AI can be complete without it. Neural Networks are at the core of Generative AI. They are algorithms modeled after the human brain, designed to recognize patterns and make decisions based on the data they've been trained on. Neural Networks have been around for decades. The advent of the internet and increasing computational power in the 21st century led to the rise of deep learning, where networks with many layers ('deep' networks) could learn from vast amounts of data. This progress has led to the evolution of Generative AI.&lt;/p&gt;

</description>
      <category>genai</category>
      <category>llm</category>
    </item>
    <item>
      <title>Hosting a Serverless Web Application in AWS - Part II</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sun, 05 Nov 2023 05:38:19 +0000</pubDate>
      <link>https://dev.to/sjejurkar/hosting-a-serverless-web-application-in-aws-part-ii-23pi</link>
      <guid>https://dev.to/sjejurkar/hosting-a-serverless-web-application-in-aws-part-ii-23pi</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the second article in this series about hosting a serverless web application in AWS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/sjejurkar/hosting-a-serverless-web-application-in-aws-part-i-332a"&gt;previous article&lt;/a&gt;, we set up a static website using AWS S3. However, there are some problems with this - we had to enable public access on our bucket and the website does not use SSL/TLS. In this article, we will enable &lt;a href="https://aws.amazon.com/cloudfront/"&gt;CloudFront&lt;/a&gt; distribution for this website and avoid these problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Amazon CloudFront
&lt;/h3&gt;

&lt;p&gt;Amazon CloudFront is a Content Delivery Network (CDN) that distributes our content globally to various edge locations. When a user requests our content, they are served from the edge location nearest to them, reducing latency. CloudFront caches our files at edge locations. This means that repeated requests for the same content are served from the cache, which is much faster. Also, serving content from the cache reduces the number of requests to our S3 bucket, which can reduce our S3 costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a CloudFront Distribution
&lt;/h3&gt;

&lt;p&gt;Navigate to the CloudFront page from the AWS console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--huoSkfFi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699114949045/f7dfd9f0-8eb9-4e92-b411-10e022b6483c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--huoSkfFi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699114949045/f7dfd9f0-8eb9-4e92-b411-10e022b6483c.png" alt="" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Create a CloudFront distribution&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CFibAAKO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699114986751/70e0e7d6-111a-4f90-bb83-9f3eae4da319.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CFibAAKO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699114986751/70e0e7d6-111a-4f90-bb83-9f3eae4da319.png" alt="" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will choose our S3 bucket in the &lt;code&gt;Origin domain&lt;/code&gt; dropdown list. For &lt;code&gt;Origin access&lt;/code&gt;, lets' select the &lt;code&gt;Origin access control settings&lt;/code&gt; option as we do not want our bucket to be publicly accessible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sUNCGYU_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699115039274/f5a40e7f-2cfc-401f-a720-c3476e0a232b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sUNCGYU_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699115039274/f5a40e7f-2cfc-401f-a720-c3476e0a232b.png" alt="" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we will create a new control settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lH6IPuyD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699115199067/f6aee078-de88-4112-824d-be43699cdeee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lH6IPuyD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699115199067/f6aee078-de88-4112-824d-be43699cdeee.png" alt="" width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll keep the default values in the &lt;code&gt;Create control setting&lt;/code&gt; windows that pop-ups. Click the &lt;code&gt;Create&lt;/code&gt; button to create the control setting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9lK5Eux_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699115227471/2c31c799-de1c-4024-bf64-196a8b60b908.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9lK5Eux_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699115227471/2c31c799-de1c-4024-bf64-196a8b60b908.png" alt="" width="759" height="775"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that we will need to manually update the bucket policy to grant permissions to our CloudFront distribution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dxn9b6Sb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699116505024/62a1d9cb-3633-4f51-8d82-98544e1df2f1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dxn9b6Sb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699116505024/62a1d9cb-3633-4f51-8d82-98544e1df2f1.png" alt="" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As this is just a sample application, choose &lt;code&gt;Do not enable security protections&lt;/code&gt; in the &lt;code&gt;Web Application Firewall&lt;/code&gt; section. For production applications, we should consider enabling security protections.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ctcYlFPv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699116581112/27ab8582-8822-4bd6-9ff7-463118fda76f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ctcYlFPv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699116581112/27ab8582-8822-4bd6-9ff7-463118fda76f.png" alt="" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's assume that a majority of our users will be from North America and Europe and choose the appropriate &lt;code&gt;Price class&lt;/code&gt;. This means that our website content will only be served by edge locations in these regions. This also means that users in other regions may see higher latency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X0xSUcRx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699116724678/da9d3c32-270f-47e1-8ddc-4047584acb58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X0xSUcRx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699116724678/da9d3c32-270f-47e1-8ddc-4047584acb58.png" alt="" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;index.html&lt;/code&gt; is the home page of our website, we will set that as the &lt;code&gt;Default root object&lt;/code&gt;. This is the content that will be returned when the user requests the root URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ACwHUxaS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699116965143/5cb8bd0a-b30e-4488-8a8a-4967987508af.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ACwHUxaS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699116965143/5cb8bd0a-b30e-4488-8a8a-4967987508af.png" alt="" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will keep the remaining options as default and click &lt;code&gt;Create distribution&lt;/code&gt; button at the bottom to create our distribution. We should see a confirmation that the new distribution was created successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QtUlT7x4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699117189422/dcdcfdd4-8a6f-457d-af4e-b2ec956a8a62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QtUlT7x4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699117189422/dcdcfdd4-8a6f-457d-af4e-b2ec956a8a62.png" alt="" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make a note of the Distribution domain name as we will use it to access our website. There should be a &lt;code&gt;Copy policy&lt;/code&gt; button on the top left corner. Click the copy icon to copy the S3 bucket policy. Now, let's navigate to the S3 bucket and update the bucket policy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mpnznWr6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699117386440/eb4129af-2dac-4366-9121-3ba46ae614a4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mpnznWr6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699117386440/eb4129af-2dac-4366-9121-3ba46ae614a4.png" alt="" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Replace the policy we created earlier with the policy that was copied above. Since we have created a CloudFront distribution to serve our website, we no longer require our bucket to be publicly accessible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1-XCbe7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699117477415/7e840868-6f70-4ae4-8f36-230bb477e767.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1-XCbe7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699117477415/7e840868-6f70-4ae4-8f36-230bb477e767.png" alt="" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will navigate back to &lt;code&gt;Edit Block public access&lt;/code&gt; for our bucket and check &lt;code&gt;Block all public access&lt;/code&gt; box and save changes. Checking this box will result in a confirmation pop-up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hi1s35YW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699117724124/14a13714-e2b5-4f0f-816d-2b1efc20e927.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hi1s35YW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699117724124/14a13714-e2b5-4f0f-816d-2b1efc20e927.png" alt="" width="688" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Type &lt;code&gt;confirm&lt;/code&gt; in the field to confirm the settings and click &lt;code&gt;Confirm&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing our website
&lt;/h3&gt;

&lt;p&gt;Our website will now be accessible using the Distribution domain name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4aDElsoL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699118072231/e9f2ab94-8321-4ac5-b738-8fd67c77ce3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4aDElsoL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699118072231/e9f2ab94-8321-4ac5-b738-8fd67c77ce3d.png" alt="" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is great but there is still one issue. The link for our website is cryptic and not ideal. So, now let us associate our domain with this CloudFront distribution so we can use a friendlier URL for our website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use our domain for our website
&lt;/h3&gt;

&lt;p&gt;Note: If you don't have a domain, you can register one for a reasonably economical price or even free (with some restrictions). You can do a web search for this.&lt;/p&gt;

&lt;p&gt;We already have a domain, &lt;code&gt;cloudbuff.in&lt;/code&gt; , registered, so we will use &lt;a href="http://tic-tac-toe.cloudbuff.in"&gt;tic-tac-toe.cloudbuff.in&lt;/a&gt; for our website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request a certificate
&lt;/h3&gt;

&lt;p&gt;Since we want our website to be secure and support SSL/TLS, we will request a new certificate for this domain from &lt;a href="https://aws.amazon.com/certificate-manager/"&gt;AWS Certificate Manager&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--07vYP_fd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121561050/ce26911f-9031-42cb-b20b-f7c4ca6c1ba4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--07vYP_fd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121561050/ce26911f-9031-42cb-b20b-f7c4ca6c1ba4.png" alt="" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On &lt;code&gt;AWS Certificate Manager&lt;/code&gt; screen, click the &lt;code&gt;Request&lt;/code&gt; button to request this new certificate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uQHhxMBZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121673532/46c821f9-90f3-4f13-a936-b999f9e509f4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uQHhxMBZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121673532/46c821f9-90f3-4f13-a936-b999f9e509f4.png" alt="" width="800" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will request a public certificate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aAyBj5q_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121773295/00b52ada-0283-49d7-9490-9d2446d91f67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aAyBj5q_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121773295/00b52ada-0283-49d7-9490-9d2446d91f67.png" alt="" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will put in the desired domain for our website as the &lt;code&gt;Fully qualified domain name&lt;/code&gt; and choose &lt;code&gt;DNS validation&lt;/code&gt; as the method to validate domain ownership. Click the &lt;code&gt;Request&lt;/code&gt; button at the bottom of the page to continue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WPwcnElN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121834170/0f07a70b-6d6c-4590-ba79-c7996360fd8f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WPwcnElN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121834170/0f07a70b-6d6c-4590-ba79-c7996360fd8f.png" alt="" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We should see a message that the certificate has been successfully requested. the status is &lt;code&gt;Pending validation&lt;/code&gt;. We need to take some additional steps before the certificate is approved.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X1LwCD1t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121989806/c321c8b4-05f9-48e2-9c80-805e629691f7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X1LwCD1t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699121989806/c321c8b4-05f9-48e2-9c80-805e629691f7.png" alt="" width="800" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the Certificate ID link and navigate to the &lt;code&gt;Domains&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y-Oyk8vU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699122125128/22e5e833-a218-4e06-b98a-717b91c946de.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y-Oyk8vU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699122125128/22e5e833-a218-4e06-b98a-717b91c946de.png" alt="" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The status is &lt;code&gt;Pending validation&lt;/code&gt; and there are two columns of interest &lt;code&gt;CNAME name&lt;/code&gt; and &lt;code&gt;CNAME value&lt;/code&gt;. We need to add a DNS record of type CNAME through the domain registration website. Our domain is registered with GoDaddy, so we will go that site and add a DNS record there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ab3gX2Py--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699122344196/461459d7-4b6a-41bd-84b9-5327e799b987.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ab3gX2Py--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699122344196/461459d7-4b6a-41bd-84b9-5327e799b987.png" alt="" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure that the type is &lt;code&gt;CNAME&lt;/code&gt; and copy the Name and Value from the AWS Certificate Manager screen. Save your changes. This will allow AWS Certificate Manager to confirm that we own this domain.&lt;/p&gt;

&lt;p&gt;Note: DNS validation can sometimes take hours depending how DNS changes are propagated and become visible to AWS Certificate Manager.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3OGgKSs0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161400975/5d746a8a-2e74-4509-8f3d-12ae395e5b14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3OGgKSs0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161400975/5d746a8a-2e74-4509-8f3d-12ae395e5b14.png" alt="" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update DNS
&lt;/h3&gt;

&lt;p&gt;Once the validation is complete, we can add a new &lt;code&gt;CNAME&lt;/code&gt; record to our DNS. This is to point subdomain &lt;code&gt;tic-tac-toe&lt;/code&gt; to our CloudFront distribution domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZhEDglkm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699122442121/c8fc2f74-3e86-400a-9d72-d4be122d1b76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZhEDglkm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699122442121/c8fc2f74-3e86-400a-9d72-d4be122d1b76.png" alt="" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update domain for distribution
&lt;/h3&gt;

&lt;p&gt;Now, we will associate this domain with our CloudFront distribution. For this, we need to edit the distribution settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BBmvyezf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161563715/00d77f22-7ae2-4e37-9ab5-973359abcb47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BBmvyezf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161563715/00d77f22-7ae2-4e37-9ab5-973359abcb47.png" alt="" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to specify our custom domain in the &lt;code&gt;Alternate domain name (CNAME)&lt;/code&gt; field. We also need to select the certificate we created earlier in the &lt;code&gt;Custom SSL certificate&lt;/code&gt; dropdown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3kEq1Vmd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161603360/6e75c049-ce8b-4b59-a0e6-58e3c0b7d373.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3kEq1Vmd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161603360/6e75c049-ce8b-4b59-a0e6-58e3c0b7d373.png" alt="" width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &lt;code&gt;Save changes&lt;/code&gt; button at the bottom to save. Now we should see our changes being deployed. This can take some time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rh1S_oyp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161766174/ed75d013-723e-4811-a4ef-bc2d44c44336.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rh1S_oyp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161766174/ed75d013-723e-4811-a4ef-bc2d44c44336.png" alt="" width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the changes are successfully deployed, we should see the date and time in the &lt;code&gt;Last modified&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rUnExmMw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161929360/7983c8af-30b8-43c2-9664-0adb3932b3cb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rUnExmMw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699161929360/7983c8af-30b8-43c2-9664-0adb3932b3cb.png" alt="" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we should be able to access our website using our custom domain &lt;a href="https://tic-tac-toe.cloudbuff.in/"&gt;https://tic-tac-toe.cloudbuff.in/&lt;/a&gt;. Note that the website is secure and uses SSL/TLS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cvxiyOwU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699162242975/f15fc387-ff20-4e3e-bd11-a8d45bacd09e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cvxiyOwU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699162242975/f15fc387-ff20-4e3e-bd11-a8d45bacd09e.png" alt="" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this article, we saw how we can use CloudFront as the CDN for our website. We also associated our custom domain with our static website hosted using S3. In subsequent articles, we will build further on this and see how we can deploy a dynamic web application in AWS without setting up any servers.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3</category>
      <category>cloudfront</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Hosting a Serverless Web Application in AWS - Part I</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sun, 05 Nov 2023 05:37:52 +0000</pubDate>
      <link>https://dev.to/sjejurkar/hosting-a-serverless-web-application-in-aws-part-i-332a</link>
      <guid>https://dev.to/sjejurkar/hosting-a-serverless-web-application-in-aws-part-i-332a</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the first article in this series about hosting a serverless web application in AWS. We will start with hosting a static website and then move towards deploying a dynamic web application.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will set up a static website using &lt;a href="https://aws.amazon.com/s3/"&gt;Amazon Simple Storage Service&lt;/a&gt; (S3). With this approach, we can easily set up a scalable website without requiring any servers.&lt;/p&gt;

&lt;p&gt;Before we jump in, let's clarify what we mean by a &lt;em&gt;static website&lt;/em&gt;. A static website consists of fixed content: HTML, CSS, and JavaScript files. A &lt;em&gt;dynamic website&lt;/em&gt;, on the other hand, depends on backend or server-side processing.&lt;/p&gt;

&lt;p&gt;We will set up a simple Tic-Tac-Toe game using HTML, CSS and JavaScript using AWS. We will use the source code available at &lt;a href="https://www.geeksforgeeks.org/simple-tic-tac-toe-game-using-javascript/"&gt;https://www.geeksforgeeks.org/simple-tic-tac-toe-game-using-javascript/&lt;/a&gt;. You can download the files from &lt;a href="https://github.com/sjejurkar/aws-serverless-app/tree/main/tic_tac_toe"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why use S3
&lt;/h3&gt;

&lt;p&gt;Amazon Simple Storage Service (S3) is a scalable object storage solution provided by AWS. It is highly durable, so you don't need to worry about losing your code or files. It offers high availability, so it greatly reduces the chances of our website being inaccessible. It is highly scalable - it can handle massive traffic spikes, making it an ideal choice for websites that demand high availability. We do not need to set up or manage any servers, so it eliminates the overhead of managing servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an S3 bucket
&lt;/h3&gt;

&lt;p&gt;First, let's create a new bucket that we want to use to store the files for our website. We will create a new S3 bucket with the name &lt;code&gt;tic-tac-toe-site-123&lt;/code&gt;. Note that the bucket names should be globally unique, so your bucket name should be different. For instance, replace the &lt;code&gt;123&lt;/code&gt; with some other number to make it unique. I am using the region &lt;code&gt;US East (N. Virginia)&lt;/code&gt; for this bucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cRIsruD3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699094518157/917362b2-b21f-486a-9bea-8930f0b8f840.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cRIsruD3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699094518157/917362b2-b21f-486a-9bea-8930f0b8f840.png" alt="Create bucket" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our website will be publicly accessible. Hence our bucket will need public access. Uncheck the &lt;code&gt;Block all public access&lt;/code&gt; box. This will uncheck all boxes underneath. Check the box in the warning section acknowledging that the bucket and objects in it will be publicly accessible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PjrTK5rk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699094740191/8fb78070-06af-4675-8bbe-5b626a2e3657.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PjrTK5rk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699094740191/8fb78070-06af-4675-8bbe-5b626a2e3657.png" alt="Unblock public access" width="800" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Leave default values for the remaining options and click &lt;code&gt;Create bucket&lt;/code&gt; to create the bucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CAgHb4Hh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095063803/e31949ce-a106-425b-9755-ebc5d48eb0ab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CAgHb4Hh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095063803/e31949ce-a106-425b-9755-ebc5d48eb0ab.png" alt="" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bucket should now appear in the list of all buckets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2It7MVEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095109416/8e59fcd5-d4b8-4c09-aa85-90e999db6a2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2It7MVEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095109416/8e59fcd5-d4b8-4c09-aa85-90e999db6a2b.png" alt="List of buckets" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Upload website files
&lt;/h3&gt;

&lt;p&gt;Click on the bucket name and go to &lt;code&gt;Objects&lt;/code&gt; tab. Click the &lt;code&gt;Upload&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KwotlqRM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095408517/48a59d4c-3d55-4d9d-8a1e-2705109e4777.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KwotlqRM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095408517/48a59d4c-3d55-4d9d-8a1e-2705109e4777.png" alt="" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the &lt;code&gt;Upload&lt;/code&gt; page, click the &lt;code&gt;Add files&lt;/code&gt; button to choose the files to be uploaded or simply drag and drop the website files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P5IbacJH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095522270/17669e29-bd0f-460a-907b-03aad593e685.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P5IbacJH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095522270/17669e29-bd0f-460a-907b-03aad593e685.png" alt="" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the folder/directory containing the website files. Select all of them to upload.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tVK7CtaO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095589305/11781ed7-68ef-4e54-a243-9ccfc738d908.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tVK7CtaO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095589305/11781ed7-68ef-4e54-a243-9ccfc738d908.png" alt="" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the files are listed, click the &lt;code&gt;Upload&lt;/code&gt; button to upload the files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rop-i-fd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095789631/2a83faa5-aeac-4cf0-bff4-45b5fea8f46e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rop-i-fd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095789631/2a83faa5-aeac-4cf0-bff4-45b5fea8f46e.png" alt="" width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add permissions policy
&lt;/h3&gt;

&lt;p&gt;The uploaded files need to be made publicly accessible. Navigate to the Permissions tab and click the &lt;code&gt;Edit&lt;/code&gt; button in &lt;code&gt;Bucket Policy&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WLxmMvUP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095862883/884cf62b-cf1b-4f6e-a451-46b5c0979a2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WLxmMvUP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699095862883/884cf62b-cf1b-4f6e-a451-46b5c0979a2a.png" alt="" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy and Paste the following policy to make the bucket content publicly readable. Note that you will need to replace &lt;code&gt;tic-tac-toe-site-123&lt;/code&gt; with the name of your bucket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement":
    [
        {
            "Sid": "PublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": ["s3:GetObject"],
            "Resource": ["arn:aws:s3:::tic-tac-toe-site-123/*"]
        }
    ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q8cF6V1u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699096343588/c5c0049c-3fea-4c45-bc1e-7c10d4f1e974.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q8cF6V1u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699096343588/c5c0049c-3fea-4c45-bc1e-7c10d4f1e974.png" alt="" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable static website hosting
&lt;/h3&gt;

&lt;p&gt;We need to let AWS know that this bucket is going to be used to host a static website. Navigate to the &lt;code&gt;Properties&lt;/code&gt; tab, scroll down to the &lt;code&gt;Static website hosting&lt;/code&gt; section and click the &lt;code&gt;Edit&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HZ9MQsor--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699096615054/04c01e30-aef4-448e-bb20-fef245c4427c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HZ9MQsor--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699096615054/04c01e30-aef4-448e-bb20-fef245c4427c.png" alt="" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the &lt;code&gt;Edit static website hosting&lt;/code&gt; page, select the &lt;code&gt;Enable&lt;/code&gt; radio button under &lt;code&gt;Static website hosting&lt;/code&gt; and &lt;code&gt;Hosting a static website&lt;/code&gt; radio button under &lt;code&gt;Hosting type&lt;/code&gt;. In the &lt;code&gt;Index document&lt;/code&gt; text field, put &lt;code&gt;index.html&lt;/code&gt; as this is the home page on our website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rYql7gwz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699096382581/b33d1d85-097a-42c9-8724-a494d4ffc97b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rYql7gwz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699096382581/b33d1d85-097a-42c9-8724-a494d4ffc97b.png" alt="" width="800" height="681"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Save changes&lt;/code&gt; to save these changes. The link to access will now appear at the bottom of &lt;code&gt;Static website hosting&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--41CiG9ST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699097074057/86e9324c-3f3b-4224-8ed8-b93d73cc3357.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--41CiG9ST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699097074057/86e9324c-3f3b-4224-8ed8-b93d73cc3357.png" alt="" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing our website
&lt;/h3&gt;

&lt;p&gt;Click the link in &lt;code&gt;Bucket website endpoint&lt;/code&gt; to open our website. We are now ready to play Tic Tac Toe game!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oekdtnRM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699097201975/bcfbb5c4-64fd-4517-85d5-86b17f2658f4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oekdtnRM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1699097201975/bcfbb5c4-64fd-4517-85d5-86b17f2658f4.png" alt="" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;It's great that our website is up and running but there are some problems with this. First, the website is not secure - it does not use HTTPS. Also, we had to make our bucket publicly accessible, which is not a good practice. In the &lt;a href="https://dev.to/sjejurkar/hosting-a-serverless-web-application-in-aws-part-ii-23pi"&gt;next article&lt;/a&gt; in this series, we will see how we can avoid these problems by using CloudFront.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Part II: Automate invoice processing using AWS Textract</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sat, 02 Sep 2023 12:10:01 +0000</pubDate>
      <link>https://dev.to/sjejurkar/part-ii-automate-invoice-processing-using-aws-textract-2lb0</link>
      <guid>https://dev.to/sjejurkar/part-ii-automate-invoice-processing-using-aws-textract-2lb0</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/sjejurkar/automate-invoice-processing-using-aws-textract-3e6e"&gt;previous article&lt;/a&gt;, we saw a quick demo showcasing how Textract can be used to extract relevant information from a scanned invoice. We took a sample invoice file, uploaded it through the AWS console and reviewed the information extracted by Textract. In this article, we will use a Python script to programmatically extract data from the same invoice using Textract SDK.&lt;/p&gt;

&lt;p&gt;We will run our code as a &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; Notebook. This can be done in several different ways. For this demo, we will run the &lt;a href="https://code.visualstudio.com/docs/datascience/jupyter-notebooks"&gt;Notebook using Visual Studio Code IDE&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's get started by cloning the repository &lt;a href="https://github.com/sjejurkar/aws-textract-demo"&gt;https://github.com/sjejurkar/aws-textract-demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before running the code, we need to do a couple of things. First, we will install the required Python packages using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, this code makes calls to Amazon Textract, so our AWS credentials need to be configured. On Linux and MacOS these are usually located in the file &lt;code&gt;~/.aws/credentials&lt;/code&gt;. On Windows, these are usually located in the file &lt;code&gt;%USERPROFILE%\.aws\credentials&lt;/code&gt;. Check &lt;a href="https://docs.aws.amazon.com/sdkref/latest/guide/file-location.html"&gt;this link&lt;/a&gt; for details.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As part of the AWS Free Tier, you can get started with Amazon &lt;br&gt;
Textract for free. The Free Tier lasts for three months, and new &amp;gt; AWS customers can analyze up to 100 invoice pages per month. &lt;br&gt;
Beyond this, there are charges for using Textract.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once the packages are installed and AWS credentials properly configured, we are ready to run the code in Notebook &lt;code&gt;invoice_demo.ipynb&lt;/code&gt;. The Notebook is in &lt;code&gt;invoice_demo&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;In the first cell of the Notebook, we will load the image of our invoice and display it. Running this cell should display the invoice image as the cell output. The image &lt;code&gt;sample-invoice-1.jpg&lt;/code&gt; is located in &lt;code&gt;documents&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sBH3eGUl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693151699147/3b584c8a-c4fe-439a-b2c8-6935c5021241.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sBH3eGUl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693151699147/3b584c8a-c4fe-439a-b2c8-6935c5021241.png" alt="Load invoice image" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we will call the Textract SDK to upload and analyze the invoice. Note that method &lt;code&gt;extractor.analyze_expense&lt;/code&gt; has been called so that Textract knows that the document we want to process is an invoice. The cell output should show that this document has only 1 page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NRYNu_pY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693152758936/385af3d2-7078-45f9-8fd8-6b17fd7247a1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NRYNu_pY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693152758936/385af3d2-7078-45f9-8fd8-6b17fd7247a1.png" alt="Call Textract SDK" width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the details extracted by Textract are available in the &lt;code&gt;document&lt;/code&gt; object. Property &lt;code&gt;document.response&lt;/code&gt; has JSON that contains all the details. We will use these details to draw boxes around the text that has been extracted. For this, we will take the existing image and based on the geometrical data extracted by Textract, draw boxes around various extracted text items. Boxes around labels will be red and those around values will be blue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uvZFi0um--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693152980660/65d001a0-e172-43a5-9b69-180eceaf80ff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uvZFi0um--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693152980660/65d001a0-e172-43a5-9b69-180eceaf80ff.png" alt="Draw boxes around text" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cell output should show the image with boxes drawn around the extracted text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--euuDcad---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693153423983/c2dbadf1-b9d9-403f-baf3-665ca41b3dca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--euuDcad---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693153423983/c2dbadf1-b9d9-403f-baf3-665ca41b3dca.png" alt="Show image with boxed text" width="800" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let's save this image as file &lt;code&gt;sample-invoice-1-boxed.png&lt;/code&gt; in the &lt;code&gt;documents&lt;/code&gt; directory for future reference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dbmE7ZoG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693153651571/47744d29-c9e0-4bca-9d1c-50bc5ad07987.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dbmE7ZoG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693153651571/47744d29-c9e0-4bca-9d1c-50bc5ad07987.png" alt="Save image" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Textract SDK allows for the extracted data to be output in various ways. Let's print the summary data and line items in a readable, tabular format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JalY1Hpx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693153805300/3c112981-95f5-498a-aa20-1ec2ea81b342.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JalY1Hpx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693153805300/3c112981-95f5-498a-aa20-1ec2ea81b342.png" alt="Show tabular format" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also output this data in CSV format as key-value pairs if required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--46ZaOUtO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693154183899/48bf3440-a28c-4df8-a4a8-2c80c513c32d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--46ZaOUtO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693154183899/48bf3440-a28c-4df8-a4a8-2c80c513c32d.png" alt="Show CSV format" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tabular and CSV outputs are easy to look at or download for further inspection but they may not be the best formats if we want to do further processing. Hence, we will create dictionaries for summary and line items to ease downstream processing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RW1m355q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693154352557/ae43be98-e54b-4555-be10-789c96f6af63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RW1m355q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693154352557/ae43be98-e54b-4555-be10-789c96f6af63.png" alt="Create dictionaries" width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cell output shows the various items being added to these dictionaries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QllIuRPW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693154665185/c43852c1-0d9b-4338-94e7-ee37b305bea7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QllIuRPW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693154665185/c43852c1-0d9b-4338-94e7-ee37b305bea7.png" alt="Print important information" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's print some relevant information from these dictionaries. Data from these dictionaries can used in downstream operations such as saving to a database, or passing to another system for further processing, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iTpnBp2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693154820187/cc8f9d02-7602-4558-aa66-e38ed78dd931.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iTpnBp2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693154820187/cc8f9d02-7602-4558-aa66-e38ed78dd931.png" alt="" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it. This article is meant to be an introduction to how Textract SDK can be used to get started with document processing. Play around with the code, try out different things and feel free to share your comments.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>textract</category>
      <category>machinelearning</category>
      <category>ocr</category>
    </item>
    <item>
      <title>Automate invoice processing using AWS Textract</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sat, 26 Aug 2023 14:58:44 +0000</pubDate>
      <link>https://dev.to/sjejurkar/automate-invoice-processing-using-aws-textract-3e6e</link>
      <guid>https://dev.to/sjejurkar/automate-invoice-processing-using-aws-textract-3e6e</guid>
      <description>&lt;p&gt;A routine task that every business must perform is to process invoices. Often, these invoices are received in paper form or as email attachments. Processing these invoices can - a) be tedious, b) consume a lot of time and c) be error-prone. This makes invoice processing a good use case for automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of Textract
&lt;/h2&gt;

&lt;p&gt;The primary challenge in processing invoices is extracting the relevant data. This is where &lt;a href="https://aws.amazon.com/textract/"&gt;Amazon Textract&lt;/a&gt; can help. It is a service provided by Amazon Web Services (AWS) that uses advanced Machine Learning (ML) algorithms to automatically extract structured and unstructured data from scanned documents, images, and PDF files. It can detect typed and handwritten text in different types of documents including invoices, financial reports, medical records, tax forms etc. Under the hood, it uses Optical Character Recognition (OCR) technology and pre-trained ML models to understand and interpret the content of documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Textract Demo
&lt;/h2&gt;

&lt;p&gt;Here is a quick demo to showcase how Textract can be used to extract relevant information from a scanned invoice.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As part of the AWS Free Tier, you can get started with Amazon &lt;br&gt;
Textract for free. The Free Tier lasts for three months, and new &amp;gt; AWS customers can analyze up to 100 invoice pages per month. &lt;br&gt;
Beyond this, there are charges for using Textract.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's jump to the AWS console and see how it works. Log into your AWS account and search for &lt;code&gt;Textract&lt;/code&gt; in AWS console. Click &lt;code&gt;Amazon Textract&lt;/code&gt; in the search results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jsQE4VQV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693036284143/5f32ae06-0819-4c49-b104-cea201c41dfb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jsQE4VQV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693036284143/5f32ae06-0819-4c49-b104-cea201c41dfb.png" alt="Search AWS Console" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This brings us to the Textract page. For this demo, we will use the US East N. Virginia region.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ojvglFC3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693036417797/1ddce9e2-1d76-4258-96e6-944b984ed7b0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ojvglFC3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693036417797/1ddce9e2-1d76-4258-96e6-944b984ed7b0.png" alt="Textract" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Try Amazon Textract&lt;/code&gt; button. This navigates to the &lt;code&gt;Analyze Document&lt;/code&gt; screen. Since we want to analyze an invoice, click on the &lt;code&gt;Analyze Expense&lt;/code&gt; option in the menu on the left.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hGLSbkkA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693057094927/85034843-d9c9-486f-819b-bbcd510af4d0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hGLSbkkA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693057094927/85034843-d9c9-486f-819b-bbcd510af4d0.png" alt="Analyze Expense" width="738" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, this screen shows a sample document and the relevant information extracted by Textract. We can see the image of a Whole Foods receipt on the left and the extracted raw text on the right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OVtWcp1v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693037670313/acd1c96c-3e56-4a3d-afed-3276fa309882.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OVtWcp1v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693037670313/acd1c96c-3e56-4a3d-afed-3276fa309882.png" alt="Sample receipt" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down and pick the &lt;code&gt;Invoice&lt;/code&gt; option. Selecting this option updates the sample to an invoice document and the text extracted from it. We want to use Textract for our sample invoice, so click &lt;code&gt;Choose document&lt;/code&gt; to upload it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--51f0vIrl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693037948747/205b7902-d031-4e5a-a8a3-91abeba024a7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--51f0vIrl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693037948747/205b7902-d031-4e5a-a8a3-91abeba024a7.png" alt="Choose invoice" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will upload an image from the local drive (download this &lt;a href="https://drive.google.com/file/d/1255w12kC4LNqjTE7NiFGJyLDnPseZ2rL/view?usp=sharing"&gt;invoice image&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mRkyc_Vy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693041665915/d08c0225-1edd-4cde-a2be-4bf66765793f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mRkyc_Vy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693041665915/d08c0225-1edd-4cde-a2be-4bf66765793f.png" alt="invoice file" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Textract will take a few seconds to process the invoice once it is uploaded. Soon, we will see our invoice with the extracted text outlined.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VzTesFcn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693041909816/2e470aaf-e220-4a6d-837a-0432c8130135.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VzTesFcn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693041909816/2e470aaf-e220-4a6d-837a-0432c8130135.png" alt="analyzed invoice" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the right, we can see important summary fields like Vendor Name, Vendor Address, Reciever Name, Receiver Address, Invoice #, Invoice Date etc. Clicking on &lt;code&gt;Line item fields&lt;/code&gt; shows the invoice line items.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--byPWgXJ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693042261598/3b959271-d170-4042-a0e2-e121034d38e3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--byPWgXJ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693042261598/3b959271-d170-4042-a0e2-e121034d38e3.png" alt="Line item fields" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The right panel shows that all the line item details have been correctly extracted. As you can see, Textract can detect and extract tables quite nicely. Another interesting feature is that if you click on any of the text items in &lt;code&gt;Results&lt;/code&gt;, it will highlight the portion of the invoice from where the text item was extracted.&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Download results&lt;/code&gt; button to download the information extracted from the invoice as a zip file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BgknmK2J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693050916272/fce1b96d-fc6e-436e-95b5-24d2c8cc914f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BgknmK2J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693050916272/fce1b96d-fc6e-436e-95b5-24d2c8cc914f.png" alt="Download Results" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The downloaded zip file has three files- two CSV and one JSON file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bm3UWQXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693058074154/042ca32f-1565-4ec5-8372-7a67509c01d5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bm3UWQXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693058074154/042ca32f-1565-4ec5-8372-7a67509c01d5.png" alt="Downloaded files" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;File &lt;code&gt;summaryFields-1.csv&lt;/code&gt; contains the extracted summary information such as the Vendor name, address, phone etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qvrs-sbu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693051721176/b2ca82a8-eb9f-4525-9f71-2caaa64fd916.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qvrs-sbu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693051721176/b2ca82a8-eb9f-4525-9f71-2caaa64fd916.png" alt="summary CSV" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;File &lt;code&gt;lineItemFields-1&lt;/code&gt; contains the line item details extracted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tv5--UwS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693051983505/aafae624-3add-41f3-957b-86ad323ad903.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tv5--UwS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1693051983505/aafae624-3add-41f3-957b-86ad323ad903.png" alt="Line items CSV" width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that it also shows the confidence scores for extract labels, column titles and values.&lt;/p&gt;

&lt;p&gt;File &lt;code&gt;analyzeExpenseResponse.json&lt;/code&gt; contains a lot more additional details including geometric information (position and size of extracted text) etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We saw in this demo that Amazon Textract goes beyond simple OCR to identify, understand, and extract data from forms and tables. The only information we provided was that the document is an invoice. We did not specify any labels, text or positions to extract. The use of pre-trained ML models makes Textract smart enough to automatically identify the appropriate labels and text relevant to an invoice.&lt;/p&gt;

&lt;p&gt;In this article, we saw a quick demo of Textract using the AWS console. Textract provides a wide range of CLI and SDKs for Python, Java, NodeJS etc. In the &lt;a href="https://dev.to/sjejurkar/part-ii-automate-invoice-processing-using-aws-textract-2lb0"&gt;next article&lt;/a&gt;, we will use a Python script to programmatically extract data from the same invoice using Textract SDK.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>textract</category>
      <category>machinelearning</category>
      <category>ocr</category>
    </item>
    <item>
      <title>Azure Functions: Hosting Plans</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sat, 11 Mar 2023 16:49:38 +0000</pubDate>
      <link>https://dev.to/sjejurkar/azure-functions-hosting-plans-28j4</link>
      <guid>https://dev.to/sjejurkar/azure-functions-hosting-plans-28j4</guid>
      <description>&lt;p&gt;In the previous articles in this &lt;a href="https://dev.to/sjejurkar/up-and-running-with-azure-functions-1m8p"&gt;series&lt;/a&gt;, we created a few functions and deployed them to Azure. In this article, we will review various options available for hosting our Function App in Azure.&lt;/p&gt;

&lt;p&gt;When we create a Function App in Azure, we must specify where our functions are hosted and where they will run. This is done by selecting a hosting plan. Azure offers three basic hosting plans:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Consumption&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Premium&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dedicated&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eB1DKKKk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1678515548796/509e2528-9962-4772-a156-874fb84b6b2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eB1DKKKk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1678515548796/509e2528-9962-4772-a156-874fb84b6b2b.png" alt="" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Consumption plan
&lt;/h2&gt;

&lt;p&gt;This is the default hosting plan and is truly serverless. The cost will depend on the amount of memory used and the number of executions of our functions. Resources used by all functions in a Function App are combined to calculate the cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We pay only when our functions are running.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Azure will automatically scale our functions based on the load.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This plan offers a free monthly grant.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : Pricing calculation for this plan is somewhat complicated. Hence it is difficult to generalize free usage, but if we have a few hundred thousand function executions per month across all functions in our subscription, those will likely get covered under the free monthly grant.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cold starts - functions may scale down to zero and when the next invocation occurs, it will require some time to start up leading to a higher response time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maximum memory available per instance is 1.5 GB RAM&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Premium plan
&lt;/h2&gt;

&lt;p&gt;With the Premium plan, specific resource capacity (vCPU and memory) is reserved to run our functions. We can choose one of the available resource configurations. If autoscaling is enabled, Azure will spin up additional instances of the Function host based on load.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mtWBj1op--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1678530195199/25ac2a5b-b716-4173-9bc1-58b49def56c2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mtWBj1op--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1678530195199/25ac2a5b-b716-4173-9bc1-58b49def56c2.png" alt="" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Pre-warmed instances to avoid cold starts and provide consistent response times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Predictable pricing as allocation of resources is determined upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;This plan can be expensive as you are paying for pre-allocated resources and also for additional instances for scaling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dedicated plan
&lt;/h2&gt;

&lt;p&gt;If we have an existing App Service plan, we can use the Dedicated plan to run our functions. Our functions will run on our App Service. If the server hosting our App Service is underutilized, this plan can help us use the remaining resources well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Functions run on an existing App Service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No additional costs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Auto-scaling is not supported&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we saw a quick overview of options available to host our Azure Functions. Note that this article covers only the basics. Pricing calculations and some finer details are beyond the scope of this article.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>azurefunctions</category>
    </item>
    <item>
      <title>Azure Functions: Output Bindings</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sun, 30 Oct 2022 12:25:51 +0000</pubDate>
      <link>https://dev.to/sjejurkar/azure-functions-output-bindings-5h2k</link>
      <guid>https://dev.to/sjejurkar/azure-functions-output-bindings-5h2k</guid>
      <description>&lt;p&gt;This is the seventh article in this &lt;a href="https://dev.to/sjejurkar/up-and-running-with-azure-functions-1m8p"&gt;series&lt;/a&gt; on Azure Functions. In this article we will take a look at output bindings.&lt;/p&gt;

&lt;p&gt;The general pattern of a function is: receive data from some source, process it in some way and send it to some destination. Bindings are a way for Azure Functions to connect to data sources and destinations. They allow our code to receive data from some source (HTTP request, Storage Queue, etc.) and optionally send data to some destination (Storage Queue, Storage Blob, etc.).&lt;/p&gt;

&lt;p&gt;There are two types of bindings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;input binding - connection to input data source&lt;/li&gt;
&lt;li&gt;output binding - connection to output data destination&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output binding
&lt;/h2&gt;

&lt;p&gt;Let's consider an example. We have an HTTP endpoint and the data posted to this endpoint must be put into a Storage Queue. Here the trigger is HTTP request and output binding is Storage Queue. HTTP is the implicit input binding in this case.&lt;/p&gt;

&lt;p&gt;First, let's go to Visual Studio code and start Azurite from the Command Palette.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o2dwxwrZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664731785680/fAIkx8Zop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o2dwxwrZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664731785680/fAIkx8Zop.png" alt="00_VSCode_azurite_start.png" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then start Azure Storage Explorer and create a new queue called &lt;code&gt;binding-queue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5BVaUrs9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062628117/su-3JvndY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5BVaUrs9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062628117/su-3JvndY.png" alt="StorageExplorer_new_queue.png" width="475" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add a new function called &lt;code&gt;BindingDemoFunction&lt;/code&gt; as shown below (source code is available on &lt;a href="https://github.com/sjejurkar/blog-azure-functions/blob/main/BindingDemoFunction.cs"&gt;GitHub&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8dK9K6Q9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062652925/X1idrvNJO.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8dK9K6Q9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062652925/X1idrvNJO.png" alt="BindingDemoFunction_code.png" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This function is similar to the &lt;code&gt;SimpleHttpFunction&lt;/code&gt; we had created in a &lt;a href="https://dev.to/sjejurkar/up-and-running-with-azure-functions-part-2-150d"&gt;previous article&lt;/a&gt; but there are some important differences.&lt;/p&gt;

&lt;p&gt;Under &lt;code&gt;FunctionName&lt;/code&gt; declaration, we have line &lt;code&gt;[return: Queue("binding-queue")]&lt;/code&gt;. This declares an output binding of type &lt;code&gt;Queue&lt;/code&gt; and queue name &lt;code&gt;binding-queue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Return type for &lt;code&gt;Run&lt;/code&gt; method is &lt;code&gt;Task&amp;lt;string&amp;gt;&lt;/code&gt; instead of &lt;code&gt;Task&amp;lt;IActionResult&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And the function returns a &lt;code&gt;string&lt;/code&gt; instead of &lt;code&gt;OkObjectResult&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;The method returns an string, the output binding takes the string, creates a message and puts it into &lt;code&gt;binding-queue&lt;/code&gt; Storage Queue. Simple and straight forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the function
&lt;/h2&gt;

&lt;p&gt;Now, let's run the function. We should see the function URL in the logs displayed in VS Code terminal. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UghyT912--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062666194/qo1gNL60U.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UghyT912--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062666194/qo1gNL60U.png" alt="BindingDemoFunction_run.png" width="800" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will use the popular &lt;a href="https://www.postman.com/downloads/"&gt;Postman&lt;/a&gt; tool to test our function. Create a POST request with &lt;code&gt;http://localhost:7071/api/BindingDemoFunction&lt;/code&gt; as URL and a simple JSON as the body. We should get back 200 status when the function runs successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DdV9hMUe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062985072/4uUPHN0n5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DdV9hMUe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062985072/4uUPHN0n5.png" alt="Postman_request.png" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's go over to Storage Explorer and verify that the message has been put into the queue. We may have to click the Refresh button for the message to be visible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fopg4BJi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062865318/3pTGVqrDB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fopg4BJi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1667062865318/3pTGVqrDB.png" alt="StorageExplorer_queue_message.png" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: We have previously set &lt;code&gt;AzureWebJobsStorage&lt;/code&gt; property as &lt;code&gt;UseDevelopmentStorage=true&lt;/code&gt; in &lt;code&gt;local.settings.json&lt;/code&gt; file. Hence the message is created correctly in the queue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we saw how to create an output binding for a Storage Queue and send a message to the queue from our Function. In the next article, we will see how to use Azure Key Vault to protect sensitive information such as connection strings, so our Function does not have direct access to it.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>azurefunctions</category>
    </item>
    <item>
      <title>Up and running with Azure Functions</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sat, 15 Oct 2022 15:58:01 +0000</pubDate>
      <link>https://dev.to/sjejurkar/up-and-running-with-azure-functions-1m8p</link>
      <guid>https://dev.to/sjejurkar/up-and-running-with-azure-functions-1m8p</guid>
      <description>&lt;p&gt;This is a series of articles to help get started with Azure Functions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/sjejurkar/up-and-running-with-azure-functions-part-1-1j22"&gt;Azure Functions: overview of concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sjejurkar/up-and-running-with-azure-functions-part-2-150d"&gt;Creating our first Azure Function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sjejurkar/deploying-our-first-function-to-azure-1kcb"&gt;Deploying our first function to Azure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sjejurkar/azure-function-with-storage-queue-trigger-p4p"&gt;Azure Function with Storage Queue Trigger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sjejurkar/deploying-storage-queue-trigger-function-479k"&gt;Deploying Storage Queue Trigger Function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sjejurkar/sending-function-logs-to-log-analytics-i3c"&gt;Sending Function logs to Log Analytics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sjejurkar/azure-functions-output-bindings-5h2k"&gt;Azure Functions: Output Bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sjejurkar/azure-functions-hosting-plans-28j4"&gt;Azure Functions: Hosting Plans&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>azure</category>
      <category>azurefunctions</category>
      <category>faas</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Sending Function logs to Log Analytics</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sat, 15 Oct 2022 15:55:53 +0000</pubDate>
      <link>https://dev.to/sjejurkar/sending-function-logs-to-log-analytics-i3c</link>
      <guid>https://dev.to/sjejurkar/sending-function-logs-to-log-analytics-i3c</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/sjejurkar/deploying-storage-queue-trigger-function-479k"&gt;previous article&lt;/a&gt;, we deployed our simple function with Storage Queue trigger to Azure cloud. We saw how to view the log stream of our Function App. While reviewing logs this way is fine for testing, it is not a practical solution once the function is deployed and running. We simply cannot watch log stream all the time. Besides, it also means that we have to leave the browser tab open for the log stream to continue. In this article, we will configure our Function App to send logs to a centralized location using Azure Log Analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Log Analytics Workspace
&lt;/h2&gt;

&lt;p&gt;First, we will create a Log Analytics Workspace for collecting our function logs. Let's go to Azure Portal and search for &lt;code&gt;log analytics&lt;/code&gt; resource. Click on &lt;code&gt;Log Analytics workspaces&lt;/code&gt; in the search results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V-1vQ_w7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665314745029/rIVZHaC5Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V-1vQ_w7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665314745029/rIVZHaC5Q.png" alt="01_Portal_log_analytics_ws.png" width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;+ Create&lt;/code&gt; to specify the details of the workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qaYxW9Rz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665314777755/zTocoFUzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qaYxW9Rz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665314777755/zTocoFUzz.png" alt="02_Portal_create_log_analytics_ws.png" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will create this new workspace in our existing &lt;code&gt;blog-functions-rg&lt;/code&gt; resource group. We will name this workspace &lt;code&gt;blog-functions-log-analytics-ws&lt;/code&gt; and specify region &lt;code&gt;East US&lt;/code&gt; that we have used so far. Click on &lt;code&gt;Review + Create&lt;/code&gt; to continue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FAfDq7L6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665314786997/xmAgx4Yhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FAfDq7L6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665314786997/xmAgx4Yhb.png" alt="03_Portal_create_log_analytics_ws.png" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We should see a &lt;code&gt;Validation passed&lt;/code&gt; message. Click on &lt;code&gt;Create&lt;/code&gt; to create the workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L2cbIbW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665314806605/Axz8H1o9-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L2cbIbW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665314806605/Axz8H1o9-.png" alt="04_create_log_analytics_ws_valid.png" width="800" height="737"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Function App Diagnostics Settings
&lt;/h2&gt;

&lt;p&gt;After the workspace is created, it needs to associated with our Function App so the logs can be routed to this workspace. To do this, we will navigate to our Function App and click on &lt;code&gt;Diagnostic settings&lt;/code&gt; item in the left menu. In the panel that opens on the right, we will click &lt;code&gt;+ Add diagnostic setting&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8JrAY5Ja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665722348726/I2TZ9byV3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8JrAY5Ja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665722348726/I2TZ9byV3.png" alt="05_add_fn_app_diag_setting.png" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will name this setting &lt;code&gt;blog-function-app-log-diag-settings&lt;/code&gt;. Since we want to send function logs to the workspace we created, check the &lt;code&gt;Function Application Logs&lt;/code&gt; and the &lt;code&gt;Send to Log Analytics workspace&lt;/code&gt; boxes. Choose the workspace we just created in the &lt;code&gt;Log Analytics workspace&lt;/code&gt; list. Click &lt;code&gt;Save&lt;/code&gt; at the top to save this setting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0vVMNE8D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665722563895/udxRlJcol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0vVMNE8D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665722563895/udxRlJcol.png" alt="06_fn_app_diag_setting_save.png" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We should now see the setting in the list of Diagnostic settings of our Function App. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OjdfPX6e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665722760517/ed3UAUFVG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OjdfPX6e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665722760517/ed3UAUFVG.png" alt="07_fn_app_diag_setting_list.png" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Invoke HTTP Function
&lt;/h2&gt;

&lt;p&gt;We need to generate some logs before we can view them. For this, let's invoke our HTTP function. Open a new browser or tab, put URL &lt;code&gt;https://blog-function-app.azurewebsites.net/api/SimpleHttpFunction&lt;/code&gt; into the address bar and press enter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n22j7MZz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665727044779/odNmrlHNd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n22j7MZz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665727044779/odNmrlHNd.png" alt="22_browser_invoke_1.png" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Each function logs a single message. We will look for these messages in the log workspace. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jRwqtthp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665727298130/0eqoYseF1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jRwqtthp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665727298130/0eqoYseF1.png" alt="07-2_fn_app_invoke_http.png" width="800" height="173"&gt;&lt;/a&gt; &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2md-3SQU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665730271588/Wq8w-0tyT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2md-3SQU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665730271588/Wq8w-0tyT.png" alt="07-3_fn_app_invoke_queue.png" width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  View Logs
&lt;/h2&gt;

&lt;p&gt;Now let's see if the logs show in the Log Analytics workspace. We will navigate to our workspace and click on &lt;code&gt;Logs&lt;/code&gt; item in the left menu. We can close the pop-up that appears on the right as we won't be using any of these queries. Instead, we will write our own query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M-nS8wPC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665723647743/a8mXHqEiM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M-nS8wPC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665723647743/a8mXHqEiM.png" alt="08_log_analytics_ws_logs.png" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Log Analytics uses Kusto Query Language (KQL) to help query and filter logs. After closing the pop-up, note that the scope is our workspace name. Select &lt;code&gt;Last 30 minutes&lt;/code&gt; as the Time range, specify &lt;code&gt;FunctionAppLogs&lt;/code&gt; as the query text and click Run button. We will see logs appearing under the Results tab.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: There can be a delay of a few minutes for the logs to make it to the workspace.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vSuZ8toN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665725227683/N6g-3RM6l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vSuZ8toN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665725227683/N6g-3RM6l.png" alt="09_log_analytics_results_1.png" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There will be a lot of messages. Azure itself writes a lot of information to the workspace. Scroll down and look for message with &lt;code&gt;Category&lt;/code&gt; as &lt;code&gt;Function.SimpleHttpFunction.User&lt;/code&gt; and you should see the log message written by the function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qPGU1d4z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665727486539/9V1p7TUgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qPGU1d4z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665727486539/9V1p7TUgb.png" alt="10_log_analytics_results_2.png" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let's get our SimpleQueueFunction to run. Go to the &lt;code&gt;blog-queue&lt;/code&gt; and add a new message &lt;code&gt;{ "msg": "Write to log analytics" }&lt;/code&gt; to the queue (see &lt;a href="https://dev.to/sjejurkar/deploying-storage-queue-trigger-function-479k"&gt;previous article&lt;/a&gt; for details). &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UNypD-lN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665729032669/y_olOCFxC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UNypD-lN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665729032669/y_olOCFxC.png" alt="11_add_queue_message.png" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we run the query again in Log Analytics workspace, we should see the message logged by &lt;code&gt;SimpleQueueFunction&lt;/code&gt;. Clicking the &lt;code&gt;&amp;gt;&lt;/code&gt; sign will expand the details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vQYwfC66--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665729041475/b3bUaRizw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vQYwfC66--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665729041475/b3bUaRizw.png" alt="12_log_analytics_results_3.png" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Log Analytics Queries
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, we can use Kusto Query Language (KQL) to query logs. When we invoked our HTTP function, a lot of messages were generated. This is going to happen every time a function is executed. If there are many function executions, there will be a large number of messages and these could be from different functions. This makes it very difficult to get to the messages that we actually need to review. KQL is quite powerful and we can use its filtering capabilities to narrow down the messages we are interested in. For e.g., to look for messages generated by a specific function, we can use a query like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FunctionAppLogs
| where Category startswith "Function."
| where FunctionName == "SimpleQueueFunction"
| project TimeGenerated, FunctionName, Level, FunctionInvocationId, Message
| order by TimeGenerated desc

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h_ZrVl61--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665731729514/Tke0ESuVN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h_ZrVl61--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665731729514/Tke0ESuVN.png" alt="13_log_analytics_results_filter_4.png" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above query will retrieve messages generated by our code as well as those generated by Azure. To see messages from only our code, we can add a &lt;code&gt;where Category endswith ".User"&lt;/code&gt; filter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FunctionAppLogs
| where Category startswith "Function." 
| where Category endswith ".User"
| where FunctionName == "SimpleQueueFunction"
| project TimeGenerated, FunctionName, Level, FunctionInvocationId, Message
| order by TimeGenerated desc

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--foIqJ4ys--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665731743878/2VzuO7a3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--foIqJ4ys--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665731743878/2VzuO7a3b.png" alt="14_log_analytics_results_filter_5.png" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that KQL appears to be similar to SQL. Here &lt;code&gt;FunctionAppLogs&lt;/code&gt; is the table. Data from this table can be filtered using &lt;code&gt;where&lt;/code&gt; clauses and &lt;code&gt;project&lt;/code&gt; clause can be used to include only the fields that we are interested in (like &lt;code&gt;select&lt;/code&gt; clause in SQL). Ordering of results is also supported.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n0lLEiu2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665731757891/2Tu_V_Wvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n0lLEiu2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665731757891/2Tu_V_Wvp.png" alt="15_log_analytics_tables.png" width="360" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Checkout a few advanced KQL query examples in &lt;a href="https://github.com/sjejurkar/azure-log-analytics-examples/blob/main/function-app-logs.md"&gt;my Github repo&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we set up a Log Analytics workspace and configured our Function App to send logs to it. This workspace acts as centralized location for retrieval and analysis of logs. We also saw how we can query and filter logs using KQL.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: It is possible to use the same Log Analytics workspace to collect all your logs - such as those from other Function Apps, App Services, Virtual Machines etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next article, we will take a look at Function App bindings.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>azurefunctions</category>
      <category>azureloganalytics</category>
    </item>
    <item>
      <title>Deploying Storage Queue Trigger Function</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sat, 08 Oct 2022 12:35:18 +0000</pubDate>
      <link>https://dev.to/sjejurkar/deploying-storage-queue-trigger-function-479k</link>
      <guid>https://dev.to/sjejurkar/deploying-storage-queue-trigger-function-479k</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/sjejurkar/azure-function-with-storage-queue-trigger-p4p"&gt;previous article&lt;/a&gt;, we created a function that gets triggered when a message arrives in a Azure Storage Queue. Using a storage emulator, we tested our function locally. Let's deploy it to Azure and test it in the cloud now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Storage Queue
&lt;/h2&gt;

&lt;p&gt;When we &lt;a href="https://dev.to/sjejurkar/deploying-our-first-function-to-azure-1kcb"&gt;set up Azure Function App&lt;/a&gt;, we created a Storage Account and linked it to our Function App. We will use the same account to create a Storage Queue. In Azure Portal, let's go to our storage account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UKS1yZzU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665227785150/iWP20ok8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UKS1yZzU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665227785150/iWP20ok8d.png" alt="05_Portal_Storage_account.png" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the Storage Account name and then on &lt;code&gt;Queues&lt;/code&gt; item in the left menu. List of queues is displayed on the right. There are no queues since we haven't created any yet. Click on &lt;code&gt;+ Queue&lt;/code&gt; icon to create a new queue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ch30hA4m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665227901200/1gegPERfX.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ch30hA4m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665227901200/1gegPERfX.png" alt="06_Portal_Storage_add_queue.png" width="729" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's create a queue with name &lt;code&gt;blog-queue&lt;/code&gt;. This is the name that we specified when we created &lt;code&gt;SimpleQueueFunction&lt;/code&gt;. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a9cVcpj1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665227909427/VMRRmiiLh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a9cVcpj1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665227909427/VMRRmiiLh.png" alt="06_Portal_Storage_new_queue.png" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We should see a message indicating that the queue was created successfully. Next, let's deploy our function to Azure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uCMJWV06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665227920003/dgE6_QLpE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uCMJWV06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665227920003/dgE6_QLpE.png" alt="07_Portal_Storage_queue.png" width="800" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy function
&lt;/h2&gt;

&lt;p&gt;Let's go to Visual Studio Code and open the project that we worked with in our &lt;a href="https://dev.to/sjejurkar/azure-function-with-storage-queue-trigger-p4p"&gt;last article&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you haven't signed in to Azure from VS Code, checkout this &lt;a href="https://dev.to/sjejurkar/deploying-our-first-function-to-azure-1kcb"&gt;previous article&lt;/a&gt; to see the steps for signing in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Open the Command Palette using keyboard shortcut &lt;code&gt;Ctrl + Shift + P&lt;/code&gt; (use &lt;code&gt;Cmd + Shift + P&lt;/code&gt; on Mac) or &lt;code&gt;View &amp;gt; Command Palette...&lt;/code&gt; menu option. Type &lt;code&gt;Azure Functions: Deploy&lt;/code&gt; into text box and select &lt;code&gt;Azure Functions: Deploy to Function App...&lt;/code&gt; option. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--55ytQQ5W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664553140554/lJQV6NWYB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--55ytQQ5W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664553140554/lJQV6NWYB.png" alt="16_VSCode_deploy_function.png" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You may get a pop-up message in VS Code asking you to set up your Azure account. If you had signed into Azure previously and get this message, open the command palette, type &lt;code&gt;Azure: Sign&lt;/code&gt; and click the Sign Out task. It will then allow you to sign in again. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vZLYWzL---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665221220555/B1c7Gm6Qx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vZLYWzL---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665221220555/B1c7Gm6Qx.png" alt="21_VSCode_Azure_signOut.png" width="800" height="203"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A list of Function Apps defined in Azure will be displayed. As we have created only one Function App &lt;code&gt;blog-function-app&lt;/code&gt;, we should see just that in the list. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--krrMWcNw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664553148649/AgsvabezS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--krrMWcNw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664553148649/AgsvabezS.png" alt="17_VSCode_deploy_select_fapp.png" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we select &lt;code&gt;blog-function-app&lt;/code&gt; for deployment, there will be a warning saying the previous deployment will be overwritten. We will click &lt;code&gt;Deploy&lt;/code&gt; to proceed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rwtDIk7V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664554113584/jgudFOm7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rwtDIk7V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664554113584/jgudFOm7c.png" alt="18_VSCode_deploy_fapp_warn.png" width="697" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A Terminal window should open in VS Code and we should soon see &lt;code&gt;Deployment to "blog-function-app" completed.&lt;/code&gt; message pop-up.&lt;br&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K4l5ZmGX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558933331/2a8ae6RGv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K4l5ZmGX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558933331/2a8ae6RGv.png" alt="18-2_VSCode_deploy_fapp_done.png" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our code has been deployed successfully. If we go back to Function App in Azure Portal and click on &lt;code&gt;Functions&lt;/code&gt; menu item, we should see both &lt;code&gt;SimpleHttpFunction&lt;/code&gt; and &lt;code&gt;SimpleQueueFunction&lt;/code&gt; in the list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m1KD7yB1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665220673038/gThWQRX1V.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m1KD7yB1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665220673038/gThWQRX1V.png" alt="04_Portal_Function_list.png" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's test our function by putting a message into the Storage Queue. First, let's enable the log stream so we can verify that our function is indeed getting triggered when a message is received in the queue. We will go to our Function App in Azure and click on &lt;code&gt;Log stream&lt;/code&gt; item in the left menu. A terminal will open to the right and in a few moments we should see that it is connected to our Function App.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1zKYRJP1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665229060362/9svhzNGJz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1zKYRJP1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665229060362/9svhzNGJz.png" alt="08_Portal_Function_log_stream.png" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's keep this browser tab open so we can come back to check log messages. We will duplicate this browser tab (hover over the current tab, do a right-click and click &lt;code&gt;Duplicate&lt;/code&gt; option from the pop-up menu) and go to the Storage Queue that we created earlier. Clicking on &lt;code&gt;+ Add message&lt;/code&gt; icon will open a pop-up window. Note that this window is similar to the window that we saw in Azure Storage Explorer tool. Let's use a simple JSON message &lt;code&gt;{ "msg": "Message from Azure Portal" }&lt;/code&gt;. Add the message text and click OK to add it to the queue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AL6_3fbj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665229288057/HK7fdi8Ww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AL6_3fbj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665229288057/HK7fdi8Ww.png" alt="08_Portal_queue_message.png" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's go back to the browser tab for log stream. We should see that the &lt;code&gt;SimpleQueueFunction&lt;/code&gt; function was executed and the message from the queue is displayed in the logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JL5x_rWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665229896286/N3rHvvj1J.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JL5x_rWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665229896286/N3rHvvj1J.png" alt="10_Portal_Function_log_stream_output.png" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's verify that the logging also works the same way for &lt;code&gt;SimpleHttpFunction&lt;/code&gt;. Open a new browser or tab, put URL &lt;code&gt;https://blog-function-app.azurewebsites.net/api/SimpleHttpFunction?name=Jack&lt;/code&gt; into the address bar and press enter. If a message like the one below is displayed, it means our function was executed successfully. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3i1YCxLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664559102015/0YR6_AVHG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3i1YCxLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664559102015/0YR6_AVHG.png" alt="22_browser_invoke_2.png" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the browser tab for log stream, we should see that the &lt;code&gt;SimpleHttpFunction&lt;/code&gt; function was executed successfully and the log message was written to the log stream.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t2zZJzzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665230001636/nMIoQ2vJ6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t2zZJzzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665230001636/nMIoQ2vJ6.png" alt="10_Portal_Function_log_stream_output_2.png" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stopping and starting Function App
&lt;/h2&gt;

&lt;p&gt;If we are still in test mode, we should consider stopping our Function App when it is not being used. We can go to our Function App and stop it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yAUDTmDm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665230704943/sj3aOdY2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yAUDTmDm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665230704943/sj3aOdY2r.png" alt="10_Portal_stop_Function.png" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we are ready to use it again, we can start our Function App back up. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PhZibEUw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665230715158/JwC46Zfub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PhZibEUw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1665230715158/JwC46Zfub.png" alt="11_Portal_start_Function.png" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article we deployed our simple function with Storage Queue trigger to Azure cloud.&lt;/p&gt;

&lt;p&gt;We saw how to view the log stream of our Function App. While looking at logs this way is fine for testing, it is not a practical solution once the function is deployed and running. We simply cannot watch log stream all the time. Besides, it also means that we have to leave the browser tab open for the log stream to continue. In the next article, we will take a look at a much better solution for this. We will configure our Function App to send logs to a centralized location using Azure Log Analytics.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>serverless</category>
      <category>azurefunctions</category>
      <category>faas</category>
    </item>
    <item>
      <title>Azure Function with Storage Queue Trigger</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Mon, 03 Oct 2022 11:29:39 +0000</pubDate>
      <link>https://dev.to/sjejurkar/azure-function-with-storage-queue-trigger-p4p</link>
      <guid>https://dev.to/sjejurkar/azure-function-with-storage-queue-trigger-p4p</guid>
      <description>&lt;p&gt;In the 4th article of this series, we will create a function that gets triggered when a message arrives in a Storage Queue. We will run a storage emulator and test our function locally.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Previous articles in this series: &lt;a href="https://dev.to/sjejurkar/up-and-running-with-azure-functions-part-1-1j22"&gt;Azure Functions: overview of concepts&lt;/a&gt;, &lt;a href="https://dev.to/sjejurkar/up-and-running-with-azure-functions-part-2-150d"&gt;Creating our first Azure Function&lt;/a&gt;, and &lt;a href="https://dev.to/sjejurkar/deploying-our-first-function-to-azure-1kcb"&gt;Deploying our first function to Azure&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we can create and test our function locally, we need to specify the queue that will be used to trigger our function. Since we don't have any queues currently, we need to create one. We want to run and test our function locally without connecting to Azure cloud, so our queue must exist locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Azurite extension for VS Code
&lt;/h2&gt;

&lt;p&gt;To create a Storage account locally on our machine, we will use &lt;a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio"&gt;Azurite&lt;/a&gt;, a free, open-source emulator that provides local environment for testing Azure Blob, Queue Storage, and Table Storage applications. The emulator provides cross-platform support on Windows, Linux, and macOS. There are number of ways to install Azurite. Since we are using VS Code as our IDE, we will install it as a VS Code extension.&lt;/p&gt;

&lt;p&gt;Click the Extensions icon on the vertical left menu. Type &lt;code&gt;azurite&lt;/code&gt; in the search field, click on &lt;code&gt;Azurite&lt;/code&gt; in the search results. Click on Install button to install this extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o3NPj6Vc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664631784838/B-JI-YNch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o3NPj6Vc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664631784838/B-JI-YNch.png" alt="VSCode_azurite_extension.png" width="446" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Azurite
&lt;/h2&gt;

&lt;p&gt;After the extension is installed, we will start up &lt;code&gt;Azurite&lt;/code&gt; so we can create a storage queue. Open the Command Palette using keyboard shortcut &lt;code&gt;Ctrl + Shift + P&lt;/code&gt; (use &lt;code&gt;Cmd + Shift + P&lt;/code&gt; on Mac) or &lt;code&gt;View &amp;gt; Command Palette...&lt;/code&gt; menu option. Type command &lt;code&gt;Azurite: Start&lt;/code&gt; and click on &lt;code&gt;Azurite: Start&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o2dwxwrZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664731785680/fAIkx8Zop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o2dwxwrZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664731785680/fAIkx8Zop.png" alt="00_VSCode_azurite_start.png" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the Azurite service starts, we should see it's status in the bottom toolbar of VS Code saying that it is running on &lt;code&gt;http://127.0.0.1:10000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Z_5ORXM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732110094/YMY7x327G.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Z_5ORXM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732110094/YMY7x327G.png" alt="00_VSCode_azurite_running_status.png" width="800" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Azure Storage Explorer
&lt;/h2&gt;

&lt;p&gt;Now that we have the Storage emulator running, we need to create our queue. For this, let's download and install &lt;a href="https://azure.microsoft.com/en-us/products/storage/storage-explorer"&gt;Azure Storage Explorer&lt;/a&gt;. Azure Storage Explorer is a desktop application to conveniently manage Azure cloud storage resources. It can also connect to Azurite and help us manage local storage.&lt;/p&gt;

&lt;p&gt;Let's start Azure Storage Explorer and click on the &lt;code&gt;Explorer&lt;/code&gt; icon on the menu on the left. We will then navigate to &lt;code&gt;Emulator &amp;amp; Attached &amp;gt; LocalStorage (Key) and Queues&lt;/code&gt;. Right click on the &lt;code&gt;Queues&lt;/code&gt; menu and click on &lt;code&gt;Create Queue&lt;/code&gt; from the pop-up menu to create a new queue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OKL82_te--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664725865957/JAy2qPz5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OKL82_te--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664725865957/JAy2qPz5n.png" alt="01_Az_Storage_Explorer_local.png" width="656" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's name the new queue &lt;code&gt;blog-queue&lt;/code&gt;. We will use this queue as the trigger for our function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1vVkCAGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664725875076/k6C01hu2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1vVkCAGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664725875076/k6C01hu2l.png" alt="02_Az_Storage_Exp_local_queue.png" width="518" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a function with Storage Queue trigger
&lt;/h2&gt;

&lt;p&gt;Our environment is now set up, so it is time to create our function. Let's go back to VS Code, open the Command Palette and type &lt;code&gt;Azure Functions: Create&lt;/code&gt; into text box and select &lt;code&gt;Azure Functions: Create Function...&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P4UN29yZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664724924826/iMLGAWeNd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4UN29yZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664724924826/iMLGAWeNd.png" alt="03_VSCode_new_fn.png" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need to choose the function trigger. We want this function to be triggered when a message is received in a Storage Queue, so type &lt;code&gt;Queue&lt;/code&gt; in the text box and choose &lt;code&gt;Azure Queue Storage trigger&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OjolR9jK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664724934580/3osSyXcCO.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OjolR9jK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664724934580/3osSyXcCO.png" alt="04_VSCode_fn_Store_Q_trg.png" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will name this function &lt;code&gt;SimpleQueueFunction&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LeWVV3_i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664724944134/7tVeG1EaW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LeWVV3_i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664724944134/7tVeG1EaW.png" alt="05_VSCode_fn_name.png" width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will continue to use CloudBuff.Function as the namespace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gyqRKwlL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664724953751/-Nkp47KW0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gyqRKwlL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664724953751/-Nkp47KW0.png" alt="06_VSCode_fn_name_space.png" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next step, we will choose &lt;code&gt;AzureWebJobsStorage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y_fsSF7l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732586378/-1BnSf12T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y_fsSF7l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732586378/-1BnSf12T.png" alt="07_VSCode_fn_storage.png" width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we will provide name of the queue we created &lt;code&gt;blog-queue&lt;/code&gt; since we want the function to run when a message arrives in this queue. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9XTEQHS3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664725475045/Oge46ajBd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9XTEQHS3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664725475045/Oge46ajBd.png" alt="08_VSCode_fn_queue_name.png" width="800" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will then be asked to select a Storage account for internal use by the Azure Functions runtime. We will go with &lt;code&gt;Use local emulator&lt;/code&gt; option. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mf3685OL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664725488750/v084Epqs_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mf3685OL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664725488750/v084Epqs_.png" alt="09_VSCode_fn_store_emulator.png" width="774" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our function will be created as &lt;code&gt;SimpleQueueFunction.cs&lt;/code&gt;. Note that &lt;code&gt;Run&lt;/code&gt; function has binding for &lt;code&gt;blog-queue&lt;/code&gt; and &lt;code&gt;AzureWebJobsStorage&lt;/code&gt; as the connection string.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--baaxhmTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732796059/Kl3K-30Pn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--baaxhmTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732796059/Kl3K-30Pn.png" alt="10_VSCode_fn_code.png" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we will be using Azurite emulator for local testing, we need to verify that it is associated with our function. To do that, we can check the &lt;code&gt;AzureWebJobsStorage&lt;/code&gt; property in file &lt;code&gt;local.settings.json&lt;/code&gt;. It should be set to &lt;code&gt;UseDevelopmentStorage=true&lt;/code&gt; as we chose the &lt;code&gt;Use local emulator&lt;/code&gt; option earlier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LNCU9ysh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732916595/X8zVTdibU.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LNCU9ysh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732916595/X8zVTdibU.png" alt="11_VSCode_fn_local_settings.png" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the function
&lt;/h2&gt;

&lt;p&gt;To run the function, click the option &lt;code&gt;Run Without Debugging&lt;/code&gt; under the &lt;code&gt;Run&lt;/code&gt; menu. VS Code will build the project and run it. Since we have two functions - SimpleHttpFunction that we created previously and SimpleQueueFunction that we just created - we should see both come up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v0XCMjmB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732930578/TxC1rpr9-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v0XCMjmB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664732930578/TxC1rpr9-.png" alt="12_VSCode_fn_run.png" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, lets add a message to &lt;code&gt;blog-queue&lt;/code&gt;. Go to Azure Storage Explorer, click on &lt;code&gt;blog-queue&lt;/code&gt; and click &lt;code&gt;Add Message&lt;/code&gt; button on the tab that opens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DKS9Px56--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664733267567/Gek6YL3d3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DKS9Px56--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664733267567/Gek6YL3d3.png" alt="13_Az_Storage_Q_add.png" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Add Message window will pop up. Let's use a simple text message &lt;code&gt;Blog Message #1&lt;/code&gt;. Add the message text and click OK to add it to the queue &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MwR9-Dj8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664733281444/nAnhlgpGq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MwR9-Dj8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664733281444/nAnhlgpGq.png" alt="14_Az_Storage_Q_new_msg.png" width="610" height="806"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding the message to the queue should trigger our function and we should see the message content being logged in the VS Code terminal window. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2YiN8edS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664733293828/y7l82vdjL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2YiN8edS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664733293828/y7l82vdjL.png" alt="15_VSCode_fn_msg_read_1.png" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's add another message to the queue. This one is a JSON message &lt;code&gt;{ "message": "This is a JSON blog message" }&lt;/code&gt;. We should also see the message being logged in the terminal window. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XcjBP2hj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664733305059/OB8OUEoPM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XcjBP2hj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664733305059/OB8OUEoPM.png" alt="15_VSCode_fn_msg_read_2.png" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it!! We have successfully created and tested our second function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we created a function that gets triggered when a message arrives in a Storage Queue and tested it locally. We saw how Azurite can be used to emulate a Storage account locally. We used Azure Storage Explorer tool to create a storage queue and add test messages to it.&lt;/p&gt;

&lt;p&gt;In the next article, we will deploy this function to Azure cloud and use an actual Azure Storage queue to test it.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>serverless</category>
      <category>azurefunctions</category>
      <category>faas</category>
    </item>
    <item>
      <title>Deploying our first function to Azure</title>
      <dc:creator>Sameer Jejurkar</dc:creator>
      <pubDate>Sat, 01 Oct 2022 08:17:40 +0000</pubDate>
      <link>https://dev.to/sjejurkar/deploying-our-first-function-to-azure-1kcb</link>
      <guid>https://dev.to/sjejurkar/deploying-our-first-function-to-azure-1kcb</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/sjejurkar/up-and-running-with-azure-functions-part-2-150d"&gt;previous article&lt;/a&gt;, we created a simple function with HTTP trigger and tested it locally. Now it's time to deploy it to Azure cloud platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an Azure account
&lt;/h2&gt;

&lt;p&gt;Before we can deploy our first function to Azure, we will need an Azure account. For this, we will go the to &lt;a href="https://azure.microsoft.com"&gt;Azure website&lt;/a&gt; and sign up for a free account. Note that you will have to provide credit card information and some additional information depending on your location. Usually, Microsoft provides up to US$ 200 worth of Azure credit when you sign up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Resource Group
&lt;/h2&gt;

&lt;p&gt;Once you are logged into Azure, the first step is to create a Resource Group. This is simply a logical container for keeping related cloud resources together. Go to the search bar at the top and type &lt;code&gt;resource groups&lt;/code&gt;. Click on &lt;code&gt;Resource groups&lt;/code&gt; in the Services section of the results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O_Vo9yp4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664457891019/ZDLqLex7-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O_Vo9yp4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664457891019/ZDLqLex7-.png" alt="01_portal_search_rg.png" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our subscription should automatically be selected on the creation form. Let's specify &lt;code&gt;blog-functions-rg&lt;/code&gt; as the name of the resource group and select a region. You can select any region you like. For e.g., you can choose the region your located in or a region close to you. We will go with &lt;code&gt;East US&lt;/code&gt;. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nIh6rCLg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458012025/z75k03_UG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nIh6rCLg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458012025/z75k03_UG.png" alt="02_portal_create_rg.png" width="800" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Review + create&lt;/code&gt; to proceed. If everything is good, a "Validation Passed" message will be displayed. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZLGVzSo0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458227929/6AdM782ux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZLGVzSo0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458227929/6AdM782ux.png" alt="03_portal_create_rg_valid.png" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on &lt;code&gt;Create&lt;/code&gt; will create the Resource Group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D6u0-5Qt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458357136/JYJhc49A3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D6u0-5Qt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458357136/JYJhc49A3.png" alt="04_portal_rg_details.png" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Function App
&lt;/h2&gt;

&lt;p&gt;Now, let's create a Function App. Type &lt;code&gt;Function App&lt;/code&gt; in the search field at the top and click on&lt;code&gt;Function App&lt;/code&gt; in the Services section of the results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LZgUmSJ2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458417200/yJ5aItmAG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LZgUmSJ2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458417200/yJ5aItmAG.png" alt="05_portal_create_rg_fn.png" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, our subscription will be automatically selected. We will use the &lt;code&gt;blog-functions-rg&lt;/code&gt; Resource Group we just created and name our Function App &lt;code&gt;blog-function-app&lt;/code&gt;. Note that this name must be globally unique because Azure uses &lt;code&gt;&amp;lt;function-name&amp;gt;.azurewebsites.net&lt;/code&gt; as the base URL for the Function App. So, you will have to choose a different name. We are going to deploy the function we created using Visual Studio Code, so we will choose &lt;code&gt;Code&lt;/code&gt; as the Publish option. We will pick &lt;code&gt;.NET&lt;/code&gt; as the Runtime stack and &lt;code&gt;6&lt;/code&gt; as the version since that is what we used to create our function. We will select the same region as the Resource Group, &lt;code&gt;East US&lt;/code&gt;, to deploy the Function App. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nplRaWKV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458507544/FtMYoBZZo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nplRaWKV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458507544/FtMYoBZZo.png" alt="06_portal_create_fn_app.png" width="800" height="691"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will use Linux as the Operating System (Windows will work too, but we will go with Linux as it appears to be the more popular choice for deploying code in the cloud). There are several pricing plans available and we will look at all the available plans in more detail in a future article. For now, we will go with the &lt;code&gt;Consumption&lt;/code&gt; plan as this is a true serverless plan. You are charged based on how many times the function is executed. Another nice thing with this plan is that first 1,000,000 executions are free. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bl5Nho50--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458673068/B61ax7KDL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bl5Nho50--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664458673068/B61ax7KDL.png" alt="07_portal_create_fn_app_2.png" width="800" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Review + create&lt;/code&gt; to proceed. A confirmation screen will be displayed. Click &lt;code&gt;Create&lt;/code&gt; to create the Function App.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wQRC_HIG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664472692166/OJyPm1UWN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wQRC_HIG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664472692166/OJyPm1UWN.png" alt="09_portal_final_create_fn_app.png" width="734" height="877"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It may take some time for the deployment to be completed. Once it is complete, we will see a confirmation. Click on &lt;code&gt;Go to resource&lt;/code&gt; to view details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AUX4ODod--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664459542902/soZphDpvi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AUX4ODod--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664459542902/soZphDpvi.png" alt="10_portal_fn_app_confirm.png" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;code&gt;Functions&lt;/code&gt; menu on the left. Currently, there are no functions under this Function App.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1FvSKwaV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664472951386/imNX5X3fe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1FvSKwaV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664472951386/imNX5X3fe.png" alt="12_portal_fn_app_functions.png" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Storage account
&lt;/h2&gt;

&lt;p&gt;We must link a general purpose Azure Storage account to the Function App we just created because it relies on Azure Storage for operations like managing triggers and logging function executions. Since we don't have a Storage account, we will create one. In Azure Portal, type &lt;code&gt;storage&lt;/code&gt; in the search bar and click on &lt;code&gt;Storage accounts&lt;/code&gt; in the Service section of the search results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K45IHEVK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664555536698/QlIJd01l2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K45IHEVK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664555536698/QlIJd01l2.png" alt="20_portal_storage_1.png" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will choose the same &lt;code&gt;blog-functions-rg&lt;/code&gt; Resource Group. We will use &lt;code&gt;blogfunctionstorage&lt;/code&gt; as the name (note that we cannot use hyphen, underscore or any other special characters in the name). We will select the same region as the Resource Group, &lt;code&gt;East US&lt;/code&gt;. We will go with &lt;code&gt;Standard&lt;/code&gt; option for Performance, since it will work for most scenarios and low latency is not really a requirement for us. For &lt;code&gt;Redundancy&lt;/code&gt; we will opt for &lt;code&gt;Locally-redundant storage (LRS)&lt;/code&gt; as it is the lowest cost option and recommended for non-critical scenarios. For production environments, it is advisable to use &lt;code&gt;Zone-redundant&lt;/code&gt;, &lt;code&gt;Geo-redundant&lt;/code&gt; or &lt;code&gt;Geo-zone-redundant&lt;/code&gt; option depending on your requirements and budget. Click &lt;code&gt;Review&lt;/code&gt; button to proceed. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--krEz4Nnb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664555545863/vJvh64Xha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--krEz4Nnb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664555545863/vJvh64Xha.png" alt="20_portal_storage_2.png" width="800" height="707"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Create&lt;/code&gt; to create the Storage Account. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HnME6QQo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664557403531/HwKJE8S1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HnME6QQo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664557403531/HwKJE8S1k.png" alt="20_portal_storage_3.png" width="800" height="826"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the Storage account is created, we should see the details in the Portal. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EasHp62Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664557414475/w0K6u3EAF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EasHp62Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664557414475/w0K6u3EAF.png" alt="20_portal_storage_4.png" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Link the Storage account to Function App
&lt;/h2&gt;

&lt;p&gt;Now let's link this Storage account to our Function App. For this, we first need to get the connection string for our Storage account. Click on &lt;code&gt;Access keys&lt;/code&gt; item in the left menu. That will display Access keys for the account. Click on the copy icon at the end of &lt;code&gt;Connection string&lt;/code&gt; field. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kjA2bVf6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664557659461/q51HOG72F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kjA2bVf6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664557659461/q51HOG72F.png" alt="20_portal_storage_5_keys.png" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the Function App by searching for &lt;code&gt;Function App&lt;/code&gt; in the menu. Click on the name of the Function App. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rJRbMx20--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558240592/m-E5JFM3T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rJRbMx20--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558240592/m-E5JFM3T.png" alt="21_portal_fn_navigate_00.png" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the &lt;code&gt;Configuration&lt;/code&gt; item from left menu. Under the &lt;code&gt;Application Settings&lt;/code&gt; tab, click on &lt;code&gt;+ New application setting&lt;/code&gt; link. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JvbfVxG6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664557712960/7bwYKD4e8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JvbfVxG6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664557712960/7bwYKD4e8.png" alt="21_portal_fn_config.png" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;Add/Edit application setting&lt;/strong&gt; pop-up form enter &lt;code&gt;AzureWebJobsStorage&lt;/code&gt; as the name and paste the Storage account connection string that we copied earlier. Click OK.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QANT2LD7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558591540/2mtCCC054.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QANT2LD7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558591540/2mtCCC054.png" alt="21_portal_fn_config_WebJobsStorage.png" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the pop-up form closes, click on Save icon to save the new setting. We have now linked our Storage account with our Function App. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BOy0YFtY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558332681/vRq7809iF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BOy0YFtY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558332681/vRq7809iF.png" alt="21_portal_fn_config_save.png" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy function
&lt;/h2&gt;

&lt;p&gt;Now, we will switch over to Visual Studio Code, open the project that we created &lt;a href="https://dev.toazure-functions-part-2"&gt;previously&lt;/a&gt; and deploy our function. Click on the Azure icon in the left menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8WfCdcg---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664473050323/0loogf32l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8WfCdcg---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664473050323/0loogf32l.png" alt="13_VSCode_Azure_login.png" width="554" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Sign in to Azure...&lt;/code&gt; option. This will open a browser window. Login with your Azure credentials.&lt;br&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--STpQI7yo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664552904456/XAwp_sCDB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--STpQI7yo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664552904456/XAwp_sCDB.png" alt="14_MS_sign_in.png" width="629" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon successful login, we should see &lt;code&gt;Select Subscriptions...&lt;/code&gt; option in VS Code. Let's select our subscription from the drop list. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yABPBX94--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664552912904/HXxq6il6P.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yABPBX94--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664552912904/HXxq6il6P.png" alt="15_VSCode_Azure_subsription.png" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open the Command Palette using keyboard shortcut &lt;code&gt;Ctrl + Shift + P&lt;/code&gt; (use &lt;code&gt;Cmd + Shift + P&lt;/code&gt; on Mac) or &lt;code&gt;View &amp;gt; Command Palette...&lt;/code&gt; menu option. Type &lt;code&gt;Azure Functions: Deploy&lt;/code&gt; into text box and select &lt;code&gt;Azure Functions: Deploy to Function App...&lt;/code&gt; option. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--55ytQQ5W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664553140554/lJQV6NWYB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--55ytQQ5W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664553140554/lJQV6NWYB.png" alt="16_VSCode_deploy_function.png" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A list of Function Apps defined in Azure will be displayed. As we have created only one Function App &lt;code&gt;blog-function-app&lt;/code&gt;, we should see just that in the list. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--krrMWcNw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664553148649/AgsvabezS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--krrMWcNw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664553148649/AgsvabezS.png" alt="17_VSCode_deploy_select_fapp.png" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we select &lt;code&gt;blog-function-app&lt;/code&gt; for deployment, there will be a warning saying the previous deployment will be overwritten. We will click &lt;code&gt;Deploy&lt;/code&gt; to proceed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rwtDIk7V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664554113584/jgudFOm7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rwtDIk7V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664554113584/jgudFOm7c.png" alt="18_VSCode_deploy_fapp_warn.png" width="697" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A Terminal window should open in VS Code and we should soon see &lt;code&gt;Deployment to "blog-function-app" completed.&lt;/code&gt; message pop-up.&lt;br&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K4l5ZmGX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558933331/2a8ae6RGv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K4l5ZmGX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664558933331/2a8ae6RGv.png" alt="18-2_VSCode_deploy_fapp_done.png" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our function code has been deployed successfully. If we go back to Function App in Azure Portal and click on &lt;code&gt;Functions&lt;/code&gt; menu item, we should see &lt;code&gt;SimpleHttpFunction&lt;/code&gt; in the list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TndaXS3Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664559086570/8Mv8etaze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TndaXS3Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664559086570/8Mv8etaze.png" alt="21_portal_fn_view_deployed.png" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that our function is deployed, let make sure it works. Open a new browser or tab, put URL &lt;code&gt;https://blog-function-app.azurewebsites.net/api/SimpleHttpFunction&lt;/code&gt; into the address bar and press enter. If a message like the one below is displayed, it means our function was executed successfully. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g_nrqOS0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664559094122/YqTYxf3Rr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g_nrqOS0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664559094122/YqTYxf3Rr.png" alt="22_browser_invoke_1.png" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's modify the URL. Add a &lt;code&gt;name&lt;/code&gt; query parameter with &lt;code&gt;Jack&lt;/code&gt; as the value:&lt;code&gt;https://blog-function-app.azurewebsites.net/api/SimpleHttpFunction?name=Jack&lt;/code&gt;We will get a different response now. As you can see that both responses match what we saw when we tested the function locally. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3i1YCxLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664559102015/0YR6_AVHG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3i1YCxLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1664559102015/0YR6_AVHG.png" alt="22_browser_invoke_2.png" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it!! We have successfully deployed our function to Azure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we deployed a simple function with HTTP trigger to Azure cloud. In the next article, we will create a function that gets triggered when a message arrives in a Storage Queue.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>serverless</category>
      <category>azurefunctions</category>
    </item>
  </channel>
</rss>
