<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[TheHTTP]]></title><description><![CDATA[TheHTTP]]></description><link>https://blog.thehttp.in</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1743881487828/0f4cc9f7-fefc-4b3c-b5b4-ef9e2b535c68.png</url><title>TheHTTP</title><link>https://blog.thehttp.in</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 14 Sep 2026 08:50:13 GMT</lastBuildDate><atom:link href="https://blog.thehttp.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[New Intl API in JavaScript 🚀]]></title><description><![CDATA[The new Intl object is the namespace for the ECMAScript Internationalization API which provides language-sensitive string comparison, number formatting, and date and time formatting in the locale-specific format.

Internationalization is the process ...]]></description><link>https://blog.thehttp.in/new-intl-api-in-javascript</link><guid isPermaLink="true">https://blog.thehttp.in/new-intl-api-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[json]]></category><category><![CDATA[internationalization]]></category><category><![CDATA[ES6]]></category><dc:creator><![CDATA[Ashutosh Panda]]></dc:creator><pubDate>Wed, 26 Oct 2022 06:15:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666734558924/yYWfCzFbH.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The new <code>Intl</code> object is the namespace for the ECMAScript Internationalization API which provides language-sensitive string comparison, number formatting, and date and time formatting in the locale-specific format.</p>
<blockquote>
<p>Internationalization is the process of designing a product, application, or document content that is suitable for a global audience. It is a set of practices that allows a product to be adapted to different languages, cultures, and regions without engineering changes. The <code>Intl</code> object is a standard way to format data in the locale-specific format.</p>
</blockquote>
<h2 id="heading-why-its-needed">Why It's Needed</h2>
<p>For decades, to make an application accessible natively in each region with the support of local elements like currency, timezone, and language-specific content developers had to use third-party libraries. The new <code>Intl</code> API trying to address the issue with the support of a few new features.</p>
<p>JavaScript being, a global language, and it's used by people all over the world. The <code>Intl</code> object is a standard way to format data in the locale-specific format. Previously, it was achieved by third-party libraries to format data in the locale-specific format, and the different operations required many different third-party libraries resulting in a bloated web and higher bundle sizes.</p>
<p>Date formatting was a major pain in the neck for developers. Because of this developers had to use third-party libraries like <a target="_blank" href="https://momentjs.com/"><code>moment.js</code></a>, <a target="_blank" href="https://date-fns.org/"><code>date-fns</code></a>, <a target="_blank" href="https://moment.github.io/luxon/#/"><code>luxon</code></a>, etc to format dates in the locale-specific format.</p>
<p>For formatting strings in the locale-specific format, developers had to use third-party client-side libraries like <code>i18next</code>, <code>react-intl</code> etc.</p>
<p>For formatting strings and numbers in the locale-specific format, developers had to use third-party libraries like <a target="_blank" href="https://www.npmjs.com/package/numeral"><code>numeral.js</code></a>, <a target="_blank" href="https://www.npmjs.com/package/accounting"><code>accounting.js</code></a>, <a target="_blank" href="https://www.npmjs.com/package/cldr-compact-number"><code>cldr-compact-number</code></a>, etc.</p>
<p>But now with the new <code>Intl</code> object, developers can format strings, numbers, and dates in the locale-specific format without using third-party libraries and standardizing the process of these.</p>
<blockquote>
<p>The Intl API has excellent support for all major browsers except <code>IE11</code>. For IE11, you can use the <a target="_blank" href="https://formatjs.io/docs/polyfills"><code>Format.js Polyfil</code></a>. </p>
<p>Each browser has a different implementation of the <code>Intl</code> object. So Output of the <code>Intl</code> object in different browsers might vary depending on the browser.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666734265555/2KtQ2xFGg.png" alt="can-i-use.png" /></p>
<h2 id="heading-intl-api">Intl API</h2>
<p><code>Intl</code> Object in Node v19.0.0 </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666793889869/kVpYgSCYT.png" alt="Intl-Nodejs.png" /></p>
<p><code>Intl</code> object in Chrome 107.0</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666793925726/Ucrsm6JeN.png" alt="Intl-Browser.png" /></p>
<p>The Intl API provides many constructor properties for various tasks. We'll explore a few of them in this article. Later I, probably will add other remaining constructors.</p>
<p><br /></p>
<h2 id="heading-intlcollator">Intl.Collator</h2>
<p>Refrence: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator">Intl.Collator</a></p>
<p>Constructor for collators, which are objects that enable language-sensitive string comparison.</p>
<h3 id="heading-syntax">Syntax</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.Collator(locales, options);
</code></pre>
<p><code>locales</code>: A string with a BCP 47 language tag, or an array of such strings. For the general form and interpretation of the locales argument, see</p>
<p><code>options</code>: An object with some or all of the following properties:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> initialOptions = {
  <span class="hljs-attr">localeMatcher</span>: <span class="hljs-string">'best fit'</span>,
  <span class="hljs-attr">usage</span>: <span class="hljs-string">'sort'</span>,
  <span class="hljs-attr">sensitivity</span>: <span class="hljs-string">'variant'</span>,
  <span class="hljs-attr">ignorePunctuation</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">numeric</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">caseFirst</span>: <span class="hljs-string">'upper'</span>,
};

<span class="hljs-keyword">const</span> collator = <span class="hljs-function">(<span class="hljs-params">
  strOne,
  strTwo,
  language = <span class="hljs-string">'en'</span>,
  options = initialOptions
</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> collatorObject = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.Collator(language, initialOptions);

  <span class="hljs-keyword">return</span> collatorObject.compare(strOne, strTwo);
};

<span class="hljs-keyword">const</span> log = <span class="hljs-built_in">console</span>.log;

log(collator(<span class="hljs-string">'a'</span>, <span class="hljs-string">'a'</span>, <span class="hljs-string">'en'</span>)); <span class="hljs-comment">// 0</span>

log(collator(<span class="hljs-string">'a'</span>, <span class="hljs-string">'A'</span>, <span class="hljs-string">'en'</span>)); <span class="hljs-comment">// 0</span>

log(collator(<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>, <span class="hljs-string">'en'</span>)); <span class="hljs-comment">// -1</span>

log(collator(<span class="hljs-string">'b'</span>, <span class="hljs-string">'a'</span>, <span class="hljs-string">'en'</span>)); <span class="hljs-comment">// 1</span>

log(collator(<span class="hljs-string">'100'</span>, <span class="hljs-string">'10'</span>, <span class="hljs-string">'en'</span>)); <span class="hljs-comment">// 1</span>

log(collator(<span class="hljs-string">'100'</span>, <span class="hljs-string">'1000'</span>, <span class="hljs-string">'en'</span>)); <span class="hljs-comment">// -1</span>

[<span class="hljs-string">'Z'</span>, <span class="hljs-string">'a'</span>, <span class="hljs-string">'z'</span>, <span class="hljs-string">'ä'</span>].sort(<span class="hljs-function">(<span class="hljs-params">acc, cur</span>) =&gt;</span> collator(acc, cur, <span class="hljs-string">'de'</span>, {})); <span class="hljs-comment">// ['a', 'ä', 'Z', 'z']</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666734722200/pOuCGRo7i.png" alt="collator.png" /></p>
<h2 id="heading-intldatetimeformat">Intl.DateTimeFormat</h2>
<p>Refrence: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat">Intl.DateTimeFormat</a></p>
<p>Constructor for objects that enable the language-sensitive date and time formatting.</p>
<h3 id="heading-syntax">Syntax</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat(locales, options);
</code></pre>
<p><code>locales</code>: A string with a BCP 47 language tag, or an array of such strings. For the general form and interpretation of the locales argument, see</p>
<p><code>options</code>: An object with some or all of the following properties:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> initialOptions = {
  <span class="hljs-attr">localeMatcher</span>: <span class="hljs-string">'best fit'</span>,
  <span class="hljs-attr">weekday</span>: <span class="hljs-string">'long'</span>,
  <span class="hljs-attr">era</span>: <span class="hljs-string">'long'</span>,
  <span class="hljs-attr">year</span>: <span class="hljs-string">'numeric'</span>,
  <span class="hljs-attr">month</span>: <span class="hljs-string">'long'</span>,
  <span class="hljs-attr">day</span>: <span class="hljs-string">'numeric'</span>,
  <span class="hljs-attr">hour</span>: <span class="hljs-string">'numeric'</span>,
  <span class="hljs-attr">minute</span>: <span class="hljs-string">'numeric'</span>,
  <span class="hljs-attr">second</span>: <span class="hljs-string">'numeric'</span>,
  <span class="hljs-attr">timeZoneName</span>: <span class="hljs-string">'long'</span>,
};

<span class="hljs-keyword">const</span> dateTimeFormat = (
  date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
  language = <span class="hljs-string">'en'</span>,
  options = initialOptions
) =&gt; {
  <span class="hljs-keyword">const</span> dateTimeFormatObject = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat(language, options);

  <span class="hljs-keyword">return</span> dateTimeFormatObject.format(date);
};

<span class="hljs-keyword">const</span> log = <span class="hljs-built_in">console</span>.log;

log(dateTimeFormat(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-string">'en'</span>)); <span class="hljs-comment">// Wednesday, October 26, 2022 Anno Domini at 2:23:13 AM India Standard Time</span>

log(dateTimeFormat(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-string">'de'</span>)); <span class="hljs-comment">// Mittwoch, 26. Oktober 2022 n. Chr. um 2:23:13 Indische Normalzeit</span>

log(dateTimeFormat(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-string">'fr'</span>)); <span class="hljs-comment">// mercredi 26 octobre 2022 après Jésus-Christ à 2:23:14 heure de l’Inde</span>

log(dateTimeFormat(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-string">'ja'</span>)); <span class="hljs-comment">// 西暦2022年10月26日水曜日 2時23分26秒 インド標準時</span>

log(dateTimeFormat(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-string">'zh'</span>)); <span class="hljs-comment">// '公元2022年10月26日星期三 印度时间 2:23:35'</span>

log(dateTimeFormat(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-string">'en'</span>, { <span class="hljs-attr">weekday</span>: <span class="hljs-string">'short'</span> })); <span class="hljs-comment">// Wed</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666734410103/lWXixlf4W.png" alt="dateTimeFormat.png" /></p>
<h2 id="heading-intlrelativetimeformat">Intl.RelativeTimeFormat</h2>
<p>Refrence: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat">Intl.RelativeTimeFormat</a></p>
<p>Constructor for objects that enable language-sensitive relative time formatting.</p>
<h3 id="heading-syntax">Syntax</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.RelativeTimeFormat(locales, options);
</code></pre>
<p><code>locales</code> : A string with a BCP 47 language tag, or an array of such strings. For the general form and interpretation of the locales argument, see</p>
<p><code>options</code>: An object with some or all of the following properties:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> initialOptions = {
  <span class="hljs-attr">localeMatcher</span>: <span class="hljs-string">'best fit'</span>,
  <span class="hljs-attr">numeric</span>: <span class="hljs-string">'auto'</span>,
  <span class="hljs-attr">style</span>: <span class="hljs-string">'long'</span>,
};

<span class="hljs-keyword">const</span> relativeTimeFormat = <span class="hljs-function">(<span class="hljs-params">
  value = <span class="hljs-number">0</span>,
  unit = <span class="hljs-string">'second'</span>,
  language = <span class="hljs-string">'en'</span>,
  options = initialOptions
</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> relativeTimeFormatObject = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.RelativeTimeFormat(language, {
    ...options,
    value,
    unit,
  });

  <span class="hljs-keyword">return</span> relativeTimeFormatObject.format(value, unit);
};

<span class="hljs-keyword">const</span> log = <span class="hljs-built_in">console</span>.log;

log(relativeTimeFormat(<span class="hljs-number">1</span>));

log(relativeTimeFormat(<span class="hljs-number">0</span>, <span class="hljs-string">'month'</span>));

log(relativeTimeFormat(<span class="hljs-number">-1</span>, <span class="hljs-string">'year'</span>));

log(relativeTimeFormat(<span class="hljs-number">10</span>, <span class="hljs-string">'hour'</span>));

log(relativeTimeFormat(<span class="hljs-number">5</span>, <span class="hljs-string">'day'</span>));

log(relativeTimeFormat(<span class="hljs-number">1</span>, <span class="hljs-string">'week'</span>));

log(relativeTimeFormat(<span class="hljs-number">1</span>, <span class="hljs-string">'month'</span>));

log(relativeTimeFormat(<span class="hljs-number">1</span>, <span class="hljs-string">'day'</span>));

log(relativeTimeFormat(<span class="hljs-number">-1</span>, <span class="hljs-string">'day'</span>));
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666734455282/dEi21yRuW.png" alt="relative-time-format.png" /></p>
<h2 id="heading-intlnumberformat">Intl.NumberFormat</h2>
<p>Refrence: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat">Intl.NumberFormat</a></p>
<p>Constructor for objects that enable language-sensitive number formatting.</p>
<h3 id="heading-syntax">Syntax</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.NumberFormat(locales, options);
</code></pre>
<p><code>locales</code>: A string with a BCP 47 language tag, or an array of such strings. For the general form and interpretation of the locales argument, see</p>
<p><code>options</code>: An object with some or all of the following properties:</p>
<blockquote>
<p>Note: The <code>style</code> property can be either <code>decimal</code> or <code>currency</code>. If <code>style</code> is <code>currency</code>, then the <code>currency</code> property must be provided as well.</p>
<p>Note: The <code>currencyDisplay</code> property can be either <code>symbol</code> or <code>code</code>. If <code>currencyDisplay</code> is <code>symbol</code>, then the <code>currency</code> property must be provided as well.</p>
<p>Note : The <code>notion</code> property can be either <code>standard</code> or <code>scientific</code>. If <code>notation</code> is <code>scientific</code>, then the <code>minimumSignificantDigits</code> and <code>maximumSignificantDigits</code> properties must be provided as well. after which we can achieve the following:</p>
</blockquote>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> initialOptions = {
  <span class="hljs-attr">localeMatcher</span>: <span class="hljs-string">'best fit'</span>,
  <span class="hljs-attr">style</span>: <span class="hljs-string">'decimal'</span>,
  <span class="hljs-attr">currency</span>: <span class="hljs-string">'USD'</span>,
  <span class="hljs-attr">currencyDisplay</span>: <span class="hljs-string">'symbol'</span>,
  <span class="hljs-attr">compactDisplay</span>: <span class="hljs-string">'short'</span>,
  <span class="hljs-attr">useGrouping</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">minimumIntegerDigits</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">minimumFractionDigits</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">maximumFractionDigits</span>: <span class="hljs-number">3</span>,
  <span class="hljs-attr">minimumSignificantDigits</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">maximumSignificantDigits</span>: <span class="hljs-number">21</span>,
  <span class="hljs-attr">notion</span>: <span class="hljs-string">'compact'</span>,
};

<span class="hljs-keyword">const</span> numberFormat = <span class="hljs-function">(<span class="hljs-params">
  number = <span class="hljs-number">0</span>,
  language = <span class="hljs-string">'en'</span>,
  options = initialOptions
</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> numberFormatObject = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.NumberFormat(language, options);

  <span class="hljs-keyword">return</span> numberFormatObject.format(number);
};

<span class="hljs-keyword">const</span> log = <span class="hljs-built_in">console</span>.log;

<span class="hljs-keyword">const</span> numberFormatOptions = {
  <span class="hljs-attr">notation</span>: <span class="hljs-string">'compact'</span>,
  <span class="hljs-attr">compactDisplay</span>: <span class="hljs-string">'short'</span>,
};

log(numberFormat(<span class="hljs-number">12343232356.789</span>, <span class="hljs-string">'en'</span>, numberFormatOptions)); <span class="hljs-comment">// 12B</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'en'</span>)); <span class="hljs-comment">// 1,000</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'de'</span>)); <span class="hljs-comment">// 1.000</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'in'</span>)); <span class="hljs-comment">// 1.000</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'fr'</span>)); <span class="hljs-comment">// 1 000</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'ja'</span>)); <span class="hljs-comment">// 1,000</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'zh'</span>)); <span class="hljs-comment">// 1,000</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'en'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>, <span class="hljs-attr">currency</span>: <span class="hljs-string">'EUR'</span> })); <span class="hljs-comment">// €1,000.00</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'de'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>, <span class="hljs-attr">currency</span>: <span class="hljs-string">'EUR'</span> })); <span class="hljs-comment">// 1.000,00 €</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'de'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>, <span class="hljs-attr">currency</span>: <span class="hljs-string">'INR'</span> })); <span class="hljs-comment">// 1.000,00 ₹</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'fr'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>, <span class="hljs-attr">currency</span>: <span class="hljs-string">'EUR'</span> })); <span class="hljs-comment">// 1 000,00 €</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'ja'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>, <span class="hljs-attr">currency</span>: <span class="hljs-string">'EUR'</span> })); <span class="hljs-comment">// €1,000.00</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'zh'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>, <span class="hljs-attr">currency</span>: <span class="hljs-string">'EUR'</span> })); <span class="hljs-comment">// €1,000.00</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'en'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'percent'</span> })); <span class="hljs-comment">// 100,000%</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'de'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'percent'</span> })); <span class="hljs-comment">// 100.000%</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'in'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'percent'</span> })); <span class="hljs-comment">// 100.000%</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'fr'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'percent'</span> })); <span class="hljs-comment">// 100 000 %</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'ja'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'percent'</span> })); <span class="hljs-comment">// 100,000%</span>

log(numberFormat(<span class="hljs-number">1000</span>, <span class="hljs-string">'zh'</span>, { <span class="hljs-attr">style</span>: <span class="hljs-string">'percent'</span> })); <span class="hljs-comment">// 100,000%</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666734483541/UIBd4sf5a.png" alt="NumberFormat.png" /></p>
<h2 id="heading-references">References</h2>
<ul>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl">MDN Intl</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator">MDN Intl.Collator</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat">MDN Intl.DateTimeFormat</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat">MDN Intl.NumberFormat</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat">MDN Intl.RelativeTimeFormat</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules">MDN Intl.PluralRules</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat">MDN Intl.ListFormat</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale">MDN Intl.Locale</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames">MDN Intl.DisplayNames</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter">MDN Intl.Segmenter</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Access AWS Cost and Billing information from IAM User]]></title><description><![CDATA[AWS Identity and Access Management (IAM) is a web service that helps you securely control access to AWS resources. You use IAM to control who is authenticated (signed in) and authorized (has permissions) to use resources.
When you create an AWS accou...]]></description><link>https://blog.thehttp.in/access-aws-cost-and-billing-information-from-iam-user</link><guid isPermaLink="true">https://blog.thehttp.in/access-aws-cost-and-billing-information-from-iam-user</guid><category><![CDATA[AWS]]></category><category><![CDATA[IAM]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Cloud Computing]]></category><dc:creator><![CDATA[Ashutosh Panda]]></dc:creator><pubDate>Tue, 25 Oct 2022 13:48:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666704674442/hzFRmLG6c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AWS Identity and Access Management (IAM) is a web service that helps you securely control access to AWS resources. You use IAM to control who is authenticated (signed in) and authorized (has permissions) to use resources.</p>
<p>When you create an AWS account, you begin with one sign-in identity that has complete access to all AWS services and resources in the account. This identity is called the AWS account <strong>root user</strong> and is accessed by signing in with the email address and password that you used to create the account. It is strongly recommended that you do not use the root user for your everyday tasks. Safeguard your root user credentials and use them to perform the tasks that only the root user can perform and use an account with the right permission for day-to-day tasks.</p>
<p>In this article, we will see how to enable AWS Cost, Usage, and Billing information to an <code>IAM</code> user.</p>
<p>You Might think you can just attach the <code>Billing</code> policy to your user and you are good to go. But there is one other step if you're doing it for the first time. You need to enable <code>Activate IAM Access to Billing Console</code> to access the billing information. You can do this by following the steps below.</p>
<h2 id="heading-create-iam-group">Create IAM Group</h2>
<ol>
<li>Log in to your AWS Console with your <code>root</code> user.</li>
<li>Go to the <code>IAM</code> service page.</li>
<li>On the left side panel, click on <code>User groups</code> and then click on <code>Create Group</code>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666705400185/gUP9sHq7U.png" alt="create-group.png" /></p>
<ol>
<li>Give a name to your group scroll down and click on <code>Create group</code>.</li>
</ol>
<blockquote>
<p>Note: You can attach policies while creating a group. But for the demo purpose, I'll create the group and attach it later.</p>
</blockquote>
<h2 id="heading-attaching-iam-policy-to-group">Attaching IAM Policy to Group</h2>
<ol>
<li>On the <code>IAM</code> service page and in there the <code>User groups</code> section you can see the created group.</li>
<li>Click on the group name.</li>
</ol>
<p>Which will take you to the group details page where you can see the group name and other details.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666704863113/LpoRiLL5D.png" alt="group-details.png" /></p>
<ol>
<li><p>Click on the <code>Permission</code> button and click on <code>Add Permission</code>.</p>
</li>
<li><p>From the drop-down select <code>Attach Policies</code>.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666704893834/Rhe-608xV.png" alt="navigate-to-permission.png" /></p>
<ol>
<li>You can Search <code>billing</code> on the filter policy search bar and attach it.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666704918419/hPieeTpum.png" alt="billing-policy.png" /></p>
<blockquote>
<p>Based on the group you might want to add permission for <code>ViewOnlyAccess</code> or <code>FullAccess</code>. For this, you'll have to create a custom policy.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666704941866/5c0cZ4Uz3.png" alt="visual-editor-policy.png" /></p>
<p>More details you can find in <a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_billing.html?icmpid=docs_iam_console#tutorial-billing-step2">here</a>.</p>
<ol>
<li>After attaching the policy click on the <code>Add Permission</code> button.</li>
</ol>
<h2 id="heading-add-user-to-group">Add User to Group</h2>
<ol>
<li>Go to the <code>IAM</code> service page.</li>
<li>On the left side panel, click on <code>User groups</code> and then click on <code>Add users</code>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666704963379/05_jhjTPN.png" alt="add-user.png" /></p>
<ol>
<li>Select the user you want to add the group to and click on <code>Add User</code>.</li>
</ol>
<h2 id="heading-activate-iam-access-to-billing-console">Activate IAM Access to Billing Console</h2>
<ol>
<li>Go to the <code>IAM</code> service page.</li>
<li>From the navigation bar, choose your account name and then choose <code>Account</code>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666705001489/wUks7LQDR.png" alt="aws-account.png" /></p>
<ol>
<li>Scroll down to the <code>IAM User and Role Access to Billing Information</code> section and click on the <code>Edit</code> button.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666705025629/xZeBnIs3y.png" alt="activate-iam-billing.png" /></p>
<ol>
<li>Enable <code>Activate IAM Access to Billing Console</code> and click on the <code>Save Changes</code> button.</li>
</ol>
<p>Now you should be able to access the billing information from your IAM user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666705110993/dY53vmFuU.png" alt="billing-dashboard.png" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we saw</p>
<ul>
<li>to enable AWS Cost, Usage, and Billing information to an <code>IAM</code> user.</li>
<li>We also saw how to create a group and attach a policy to it.</li>
<li>How to add a user to a group.</li>
<li>How to activate IAM Access to Billing Console.</li>
</ul>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html">AWS IAM User</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html">AWS IAM Policy</a></li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html">AWS IAM Group</a></p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_billing.html?icmpid=docs_iam_console#tutorial-billing-step2">AWS IAM Access to Billing Console</a></p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/control-access-billing.html">Activating access to the AWS Billing console</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[What is SNS and how it works?]]></title><description><![CDATA[Amazon Simple notification service (SNS) is a web service that coordinates and manages the delivery or sending of messages to subscribing endpoints or clients. SNS provides topics for high-throughput, push-based, many-to-many messaging. It is a highl...]]></description><link>https://blog.thehttp.in/what-is-sns-and-how-it-works</link><guid isPermaLink="true">https://blog.thehttp.in/what-is-sns-and-how-it-works</guid><category><![CDATA[Cloud]]></category><category><![CDATA[AWS]]></category><category><![CDATA[AWS SNS]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Ashutosh Panda]]></dc:creator><pubDate>Mon, 24 Oct 2022 11:40:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666611155675/VO6IskjOp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Amazon Simple notification service (SNS) is a web service that coordinates and manages the delivery or sending of messages to subscribing endpoints or clients. SNS provides topics for high-throughput, push-based, many-to-many messaging. It is a highly available, durable, secure, fully managed <a target="_blank" href="https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">Pub/Sub</a> messaging service that can be used to decouple microservices, distributed systems, and serverless applications. It helps to decouple the components of an application and allows them to scale independently and build loosely coupled systems which can also be coined as event-driven architecture (EDA).</p>
<h2 id="heading-how-sns-works">How SNS works?</h2>
<p>Amazon SNS sends notifications two ways, A2A and A2P. A2A provides high-throughput, push-based, many-to-many messaging between distributed systems, microservices, and event-driven serverless applications. These applications include Amazon Simple Queue Service (SQS), Amazon Kinesis Data Firehose, AWS Lambda, and other HTTP/S endpoints or to any other endpoint that supports the Simple Notification Service (SNS) protocol. A2P functionality lets you send messages to your customers with SMS texts, push notifications, and email. SNS also provides a simple, cost-effective, push-based mechanism to distribute notifications to large numbers of subscribers.</p>
<ol>
<li><p>SNS is a highly available, durable, secure, and scalable pub/sub messaging system with very low latency.</p>
</li>
<li><p>SNS is a fully managed service, which means that AWS takes care of the infrastructure and maintenance of the service. You don't need to worry about the underlying infrastructure, such as the servers, operating systems, and network.</p>
</li>
<li><p>SNS is a pub/sub messaging system, which means that the publisher does not need to know the subscribers. The publisher sends a message to the topic, and the message is delivered to all the subscribers of the topic.</p>
</li>
<li><p>SNS is a highly available service, which means that it is designed to have a high degree of fault tolerance and to be able to recover from failures quickly, AWS guarantees 99.9% accuracy on SNS service.</p>
</li>
<li><p>SNS is a durable service, which means that it can store messages for a long time. SNS is a secure service, which means that it uses encryption and authentication to protect your data.</p>
</li>
<li><p>It is a scalable service, which means that it can handle a large number of requests and messages, and it provides high throughput.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666560195288/0-pE7pFA4.png" alt="sns-doc.png" /></p>
<h2 id="heading-sns-topics">SNS Topics</h2>
<p>A topic is a logical access point and communication channel for a publisher to post a message that is immediately available for subscribers to consume. A topic is a container for messages that are published to the topic. Subscribers can be applications or end users. When a publisher sends a message to a topic, Amazon SNS delivers the message to each subscriber. A topic can have multiple subscribers, and each subscriber can have multiple protocols.</p>
<h2 id="heading-sns-subscriptions">SNS Subscriptions</h2>
<p>Subscriptions are the mechanism that delivers messages to subscribing endpoints or clients. A subscription is a communication channel to deliver notifications from a topic to subscribers. A subscription is an association between a topic and an endpoint. Subscriptions are uni-directional. A subscription can deliver notifications to one or more endpoints and to one or more protocols.</p>
<p>while creating a subscription, you can choose the protocol and endpoint. The protocol is the mechanism by which SNS delivers notifications to the endpoint. The endpoint is the location where the notification is sent.</p>
<blockquote>
<p>Upon adding a subscription, SNS sends a confirmation message to the endpoint. The endpoint must confirm the subscription by sending a message back to SNS. The confirmation message is sent to the endpoint using the protocol that you specified when you created the subscription. For example, if you created a subscription with the HTTP protocol, the confirmation message is sent to the endpoint using the HTTP protocol to the endpoint with <code>POST</code> request. If you created a subscription with the email protocol, the confirmation message is sent to the endpoint using the email protocol. If you create a subscription with SQS as the protocol, the correct policy must be attached to the SQS queue.</p>
</blockquote>
<h2 id="heading-sns-message-delivery">SNS Message Delivery</h2>
<p>SNS provides two types of message delivery, point-to-point, and publish-subscribe. Point-to-point delivery is a one-to-one communication between a sender and a receiver. Publish-subscribe delivery is a one-to-many communication between a sender and multiple receivers. SNS uses publish-subscribe delivery to send messages to multiple subscribers</p>
<h2 id="heading-sns-message-delivery-guarantees">SNS Message Delivery Guarantees</h2>
<p>SNS provides two types of message delivery guarantees, at-least-once and exactly-once. At-least-once delivery is a message delivery guarantee that ensures that a message is delivered at least once. Exactly-once delivery is a message delivery guarantee that ensures that a message is delivered exactly once. SNS uses at-least-once delivery by default. SNS provides exactly-once delivery by using the SNS FIFO (first-in-first-out) topics.</p>
<h2 id="heading-sns-message-delivery-order">SNS Message Delivery Order</h2>
<p>SNS provides two types of message delivery orders, unordered and ordered. Unordered delivery is a message delivery order that ensures that a message is delivered in any order. Ordered delivery is a message delivery order that ensures that a message is delivered in the same order as it was sent. SNS uses unordered delivery by default. SNS provides ordered delivery by using the SNS FIFO (first-in-first-out) topics.</p>
<h2 id="heading-sns-message-delivery-delay">SNS Message Delivery Delay</h2>
<p>SNS provides two types of message delivery delay, immediate and delayed. Immediate delivery is a message delivery delay that ensures that a message is delivered immediately. Delayed delivery is a message delivery delay that ensures that a message is delivered after a specified delay. SNS uses immediate delivery by default. SNS provides delayed delivery by using the SNS FIFO (first-in-first-out) topics.</p>
<h2 id="heading-sns-message-delivery-retries">SNS Message Delivery Retries</h2>
<p>SNS provides two types of message delivery retries, automatic and manual. Automatic retries are the retries that are performed by SNS automatically. Manual retries are the retries that are performed by the subscriber. SNS uses automatic retries by default. SNS provides manual retries by using the SNS FIFO (first-in-first-out) topics.</p>
<h2 id="heading-sns-message-delivery-failures">SNS Message Delivery Failures</h2>
<p>SNS provides two types of message delivery failures, permanent and transient. Permanent failures are the failures that are not recoverable. Transient failures are the failures that are recoverable. SNS uses permanent failures by default. SNS provides transient failures by using the SNS FIFO (first-in-first-out) topics.</p>
<h2 id="heading-sns-dead-letter-queue">SNS Dead Letter Queue</h2>
<p>SNS provides two types of dead letter queues, standard, and FIFO. Standard dead letter queues are the dead letter queues that are used to store messages that failed to be delivered to the subscribers. FIFO dead letter queues are the dead letter queues that are used to store messages that failed to be delivered to the subscribers in the same order as they were sent. SNS uses standard dead letter queues by default. SNS provides FIFO dead letter queues by using the SNS FIFO (first-in-first-out) topics.</p>
<h2 id="heading-sns-message-delivery-status">SNS Message Delivery Status</h2>
<p>SNS provides two types of message delivery status, success (200 status code) and failure (400 status code). Success status is the status that is returned when a message is delivered successfully. Failure status is the status that is returned when a message is not delivered successfully. SNS uses success status by default. SNS provides failure status by using the SNS FIFO (first-in-first-out) topics.</p>
<h1 id="heading-use-cases">Use Cases</h1>
<ol>
<li>Integrate your applications with FIFO messaging<ul>
<li>Deliver messages in a strictly ordered, first in, first out (FIFO) manner to maintain accuracy and consistency across independent applications.</li>
</ul>
</li>
<li><p>Securely encrypt notification message delivery</p>
<ul>
<li>Encrypt messages with AWS Key Management Service (KMS), ensure traffic privacy with AWS PrivateLink, and control access with resource policies and tags.</li>
</ul>
</li>
<li><p>Capture and fan out events from over 60 AWS services</p>
<ul>
<li>Fan out events across AWS categories, such as analytics, compute, containers, databases, IoT, machine learning (ML), security, and storage.</li>
</ul>
</li>
<li><p>Send SMS texts to customers across over 240 countries</p>
<ul>
<li><p>Send SMS messages to customers in over 240 countries and territories, including the United States, Canada, Australia, and the United Kingdom.</p>
</li>
<li><p>Use worldwide SMS, with redundancy across providers. Set SMS origination identity with a sender ID, long code, short code, TFN, or 10DLC. Use Amazon Pinpoint to send SMS messages to customers in the United States, Canada, Australia, and the United Kingdom.</p>
</li>
</ul>
</li>
</ol>
<h1 id="heading-pricing">Pricing</h1>
<p>Amazon SNS is a pay-as-you-go service. You pay only for the resources you use. There are no upfront costs or long-term commitments. You pay for the number of requests you make to Amazon SNS, the number of messages you publish to Amazon SNS topics, and the number of messages you receive from Amazon SNS subscriptions. You can also choose to pay for the number of messages that are delivered to your endpoints. For more information, see <a target="_blank" href="https://aws.amazon.com/sns/pricing/">Amazon SNS Pricing</a>.</p>
<p>SNS has also a free tier. It includes 1 million free requests, 100,000 free HTTP/S deliveries, and 1000 Email deliveries as of 24th Oct 2022. For more information, see <a target="_blank" href="https://aws.amazon.com/sns/pricing/">Amazon SNS Free Tier</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Convert text to natural-sounding human voices using Amazon Polly]]></title><description><![CDATA[For years, brands have relied on famous actors to provide narration for ads, which creates a sense of familiarity and imparts the desired tone. But actors can be expensive, and their voices usually have a limited shelf life for commercial use. A synt...]]></description><link>https://blog.thehttp.in/convert-text-to-natural-sounding-human-voices-using-amazon-polly</link><guid isPermaLink="true">https://blog.thehttp.in/convert-text-to-natural-sounding-human-voices-using-amazon-polly</guid><category><![CDATA[AWS]]></category><category><![CDATA[Amazon Web Services]]></category><category><![CDATA[lambda]]></category><category><![CDATA[AI]]></category><category><![CDATA[serverless]]></category><dc:creator><![CDATA[Ashutosh Panda]]></dc:creator><pubDate>Thu, 20 Oct 2022 20:41:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666250764747/Nrqku7hMy.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For years, brands have relied on famous actors to provide narration for ads, which creates a sense of familiarity and imparts the desired tone. But actors can be expensive, and their voices usually have a limited shelf life for commercial use. A synthetic voice offers an effective alternative.</p>
<p>Furthermore, AI voices make the process of editing voiceovers, quick and easy. Users can simply make the necessary changes to their script and modify the AI voice automatically. Synthetic voice is now accessible more than ever in this growing AI and ML world. the possibility of synthetic automated voice is only limited by your imagination. That being said the process of converting Text / SSML to natural-sounding voices isn't as difficult as used to be.</p>
<p>In this article, we'll see how <strong>AWS Polly</strong> which is an AI-based text-to-speech service can be used to convert text to speech in your desired language. We'll also see how to use <strong>AWS Lambda</strong> to convert text to speech and save it to <strong>AWS S3 and DynamoDB</strong>.</p>
<h2 id="heading-services">Services</h2>
<h3 id="heading-what-is-amazon-polly">What is Amazon Polly?</h3>
<p>Amazon Polly is a service that turns text into lifelike speech. It's a text-to-speech (TTS) service that uses advanced deep learning technologies to synthesize speech that sounds like a human voice. It provides dozens of lifelike voices in multiple languages. You can create applications that talk and build entirely new categories of speech-enabled products. Polly is a fully managed service that makes it easy for developers to add speech to their applications.</p>
<blockquote>
<p>Polly is a paid service. You can use the free tiers. After that, you'll have to pay for the service. The free tier includes 5 million characters per month for 12 months. You can find the pricing details <a target="_blank" href="https://aws.amazon.com/polly/pricing/">here</a>.</p>
</blockquote>
<ol>
<li><p>With <code>AWS Polly</code> developers can customize and control speech output that supports lexicons and Speech Synthesis Markup Language (SSML) tags.</p>
</li>
<li><p>Store and redistribute speech in standard formats like MP3 and OGG.</p>
</li>
<li><p>Quickly deliver lifelike voices and conversational user experiences in consistently fast response times.</p>
</li>
</ol>
<p><strong>How Polly Works</strong>
This is an Image demonstrating how Polly works straight out of the AWS documentation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666275639024/JvbQrP4dN.png" alt="Product-Page.png" /></p>
<h3 id="heading-how-to-use-aws-polly">How to use AWS Polly?</h3>
<p>For a Quick Simple Demo of AWS Polly, you can use the <a target="_blank" href="https://us-east-1.console.aws.amazon.com/polly/home/SynthesizeSpeech">AWS Polly Service Page</a>.</p>
<ol>
<li>Go to the <a target="_blank" href="https://aws.amazon.com/polly/">AWS Polly</a> console and click on the <code>Get Started Now</code> button.</li>
<li>Click on <code>Text to Speech</code>.</li>
<li>Select the language and voice you want to use.</li>
<li>Enter the text you want to convert to speech.</li>
<li>Click on <code>Play</code> to listen to the speech.</li>
<li>Click on <code>Download</code> to download the speech.</li>
</ol>
<p>Without further ado, let's get started and build a simple application that converts text to speech and saves the MP3 file it to AWS S3 and the Metadata to DynamoDB.</p>
<h3 id="heading-what-is-aws-lambda">What is AWS Lambda?</h3>
<p>AWS Lambda is a compute service that lets you run code without provisioning or managing servers. AWS Lambda executes your code only when needed and scales automatically, from a few requests per day to thousands per second. You pay only for the compute time you consume - there is no charge when your code is not running. With Lambda, you can run code for virtually any type of application or backend service - all with zero administration. Just upload your code and Lambda takes care of everything required to run and scale your code with high availability. You can set up your code to automatically trigger from other AWS services or call it directly from any web or mobile app.</p>
<h3 id="heading-what-is-aws-s3">What is AWS S3?</h3>
<p>AWS S3 is a simple storage service that offers an extremely durable, highly available, and infinitely scalable object storage infrastructure at very low costs. It is designed to make web-scale computing easier for developers. Amazon S3 provides developers and IT teams with secure, durable, highly-scalable object storage. Amazon S3 is easy to use, with a simple web services interface to store and retrieve any amount of data from anywhere on the web.</p>
<h3 id="heading-what-is-dynamodb">What is DynamoDB?</h3>
<p>AWS DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability. DynamoDB lets you offload the administrative burdens of operating and scaling a distributed database, so that you don't have to worry about hardware provisioning, setup, and configuration, replication, software patching, or cluster scaling.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ol>
<li>You need to have an AWS account. If you don't have one, you can create one <a target="_blank" href="https://aws.amazon.com/">here</a>.</li>
<li>You need to have Node.js installed on your machine. You can download it from <a target="_blank" href="https://nodejs.org/en/">here</a>.</li>
<li>You need to have the AWS CLI installed on your machine. You can download it from <a target="_blank" href="https://aws.amazon.com/cli/">here</a>.</li>
<li>You need to have AWS CLI configured. you can configure it by running <code>aws configure</code>.</li>
<li>You need to have the Serverless Framework installed on your machine. You can download it from <a target="_blank" href="https://serverless.com/framework/docs/providers/aws/guide/installation/">here</a>.</li>
</ol>
<h2 id="heading-steps">Steps</h2>
<blockquote>
<p><strong>Note:</strong> You can find the complete code for this article in my GitHub Repository.</p>
</blockquote>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/ashutosh4336/speak-polly-serverless">https://github.com/ashutosh4336/speak-polly-serverless</a></div>
<h3 id="heading-initializing-the-app">Initializing the app.</h3>
<p>With the serverless framework, we can generate a boilerplate code for our application. We'll use the <code>serverless create</code> command to generate the boilerplate code.</p>
<pre><code class="lang-bash">sls create --template aws-nodejs --path speak-polly-app --name speak-polly-app
</code></pre>
<p>Here the <code>--template</code> signifies the template we want to use. We're using the <code>aws-nodejs</code> template. The <code>--path</code> signifies the path where we want to create the project. We're creating the project in the <code>speak-polly-app</code> folder. The <code>--name</code> signifies the name of the project. We're naming the project as <code>speak-polly-app</code>.</p>
<p>After running the above command, you'll see a folder named <code>speak-polly-app</code> in your current directory. This folder contains the boilerplate code for our application.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> speak-polly-app
</code></pre>
<p>Now, let's install the dependencies for our application. We'll be using <code>aws-sdk</code> and <code>uuid</code> packages. The <code>aws-sdk</code> package will help us to interact with AWS services and APIs. The <code>uuid</code> package will help us to generate a unique ID for our speech.</p>
<pre><code class="lang-bash">npm install aws-sdk uuid
</code></pre>
<h3 id="heading-code">Code</h3>
<p>Now, let's open the <code>handler.js</code> file in our project. This file contains the code for our application.</p>
<pre><code class="lang-javascript"><span class="hljs-meta">'use strict'</span>;

<span class="hljs-keyword">const</span> AWS = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-sdk'</span>);
<span class="hljs-keyword">const</span> { <span class="hljs-attr">v4</span>: uuidV4 } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'uuid'</span>);
<span class="hljs-keyword">const</span> Polly = <span class="hljs-keyword">new</span> AWS.Polly({ <span class="hljs-attr">apiVersion</span>: <span class="hljs-string">'2016-06-10'</span> });
<span class="hljs-keyword">const</span> S3 = <span class="hljs-keyword">new</span> AWS.S3({ <span class="hljs-attr">apiVersion</span>: <span class="hljs-string">'latest'</span> });
<span class="hljs-keyword">const</span> dynamodb = <span class="hljs-keyword">new</span> AWS.DynamoDB({ <span class="hljs-attr">apiVersion</span>: <span class="hljs-string">'2012-08-10'</span> });

<span class="hljs-built_in">module</span>.exports.speakPolly = <span class="hljs-keyword">async</span> (event) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> records = event[<span class="hljs-string">'Records'</span>];

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> record <span class="hljs-keyword">of</span> records) {
      <span class="hljs-keyword">const</span> bucketName = record[<span class="hljs-string">'s3'</span>][<span class="hljs-string">'bucket'</span>][<span class="hljs-string">'name'</span>];
      <span class="hljs-keyword">const</span> objectKey = record[<span class="hljs-string">'s3'</span>][<span class="hljs-string">'object'</span>][<span class="hljs-string">'key'</span>];
      <span class="hljs-comment">// const objectSize = record['s3']['object']['size'];</span>

      <span class="hljs-keyword">const</span> objectDetails = <span class="hljs-keyword">await</span> getObjectFromS3(bucketName, objectKey);
      <span class="hljs-keyword">const</span> text = objectDetails.Body.toString(<span class="hljs-string">'utf-8'</span>);
      <span class="hljs-keyword">const</span> voiceId = process.env.VOICE_AGENT || <span class="hljs-string">'Carla'</span>;

      <span class="hljs-keyword">const</span> params = {
        <span class="hljs-attr">Engine</span>: <span class="hljs-string">'standard'</span>,
        <span class="hljs-attr">OutputFormat</span>: <span class="hljs-string">'mp3'</span>,
        <span class="hljs-attr">SampleRate</span>: <span class="hljs-string">'22050'</span>,
        <span class="hljs-attr">Text</span>: text,
        <span class="hljs-attr">TextType</span>: <span class="hljs-string">'text'</span>,
        <span class="hljs-attr">VoiceId</span>: voiceId,
      };

      <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> Polly.synthesizeSpeech(params).promise();

      <span class="hljs-keyword">const</span> destinationBucketName = process.env.AUDIO_BUCKET;
      <span class="hljs-keyword">const</span> mp3FileKey = uuidV4();
      <span class="hljs-keyword">const</span> destinationObjectKey = <span class="hljs-string">`<span class="hljs-subst">${mp3FileKey}</span>.mp3`</span>;

      <span class="hljs-keyword">const</span> s3Params = {
        <span class="hljs-attr">Bucket</span>: destinationBucketName,
        <span class="hljs-attr">Key</span>: destinationObjectKey,
        <span class="hljs-attr">data</span>: data.AudioStream,
        <span class="hljs-attr">ContentType</span>: <span class="hljs-string">'audio/mpeg'</span>,
      };

      <span class="hljs-keyword">const</span> dynamoTableName = process.env.DYNAMODB_TABLE;

      <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all([
        putObjectToS3(s3Params),
        putItemToDynamoDB(dynamoTableName, {
          <span class="hljs-attr">id</span>: { <span class="hljs-attr">S</span>: mp3FileKey },
          <span class="hljs-attr">text</span>: { <span class="hljs-attr">S</span>: text },
          <span class="hljs-attr">voiceId</span>: { <span class="hljs-attr">S</span>: voiceId },
          <span class="hljs-attr">bucket</span>: { <span class="hljs-attr">S</span>: destinationBucketName },
          <span class="hljs-attr">createdAt</span>: { <span class="hljs-attr">S</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString() },
          <span class="hljs-attr">updatedAt</span>: { <span class="hljs-attr">S</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString() },
        }),
      ]);
    }

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(
        { <span class="hljs-attr">message</span>: <span class="hljs-string">'Successfully executed'</span>, <span class="hljs-attr">data</span>: event },
        <span class="hljs-literal">null</span>,
        <span class="hljs-number">2</span>
      ),
    };
  } <span class="hljs-keyword">catch</span> (err) {

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">statusCode</span>: <span class="hljs-number">500</span>,
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Error'</span>, <span class="hljs-attr">data</span>: err }, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>),
    };
  }
};

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getObjectFromS3</span>(<span class="hljs-params">bucket_name, object_key</span>) </span>{
  <span class="hljs-keyword">const</span> params = {
    <span class="hljs-attr">Bucket</span>: bucket_name,
    <span class="hljs-attr">Key</span>: unquotePlus(object_key),
  };

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> S3.getObject(params).promise();
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">putObjectToS3</span>(<span class="hljs-params">{ Bucket, Key, data, ContentType }</span>) </span>{
  <span class="hljs-keyword">const</span> params = {
    <span class="hljs-attr">Bucket</span>: Bucket,
    <span class="hljs-attr">Key</span>: Key,
    <span class="hljs-attr">Body</span>: data,
    <span class="hljs-attr">ContentType</span>: ContentType,
  };

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> S3.putObject(params).promise();
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">putItemToDynamoDB</span>(<span class="hljs-params">TableName, Item</span>) </span>{
  <span class="hljs-keyword">const</span> params = {
    <span class="hljs-attr">TableName</span>: TableName,
    <span class="hljs-attr">Item</span>: Item,
  };

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> dynamodb.putItem(params).promise();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unquotePlus</span>(<span class="hljs-params">s</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">decodeURIComponent</span>(s.replace(<span class="hljs-regexp">/\+/g</span>, <span class="hljs-string">' '</span>));
}
</code></pre>
<h4 id="heading-lets-understand-the-lambda-function">Let's understand the Lambda Function.</h4>
<p>The default handler function is <code>speakPolly</code>. This function will be called when we invoke our Lambda function. The <code>event</code> object contains the details of the event that triggered the Lambda function. In our case, the event object will contain the details of the S3 object that was created.</p>
<p>With the <code>event</code> object we'll get the details of the S3 object that was uploaded. We'll get the bucket name, object key from the event object, and many other details like object size. We'll use the <code>getObjectFromS3</code> function to get the object from the S3 bucket. With <code>toString</code> method we'll get the raw text from the object and text to generate the speech.</p>
<p>We'll use the <code>Polly.synthesizeSpeech</code> function to generate the speech. The <code>Polly.synthesizeSpeech</code> function will return the speech in the form of an audio stream. We'll use the <code>putObjectToS3</code> function to put the audio stream to the S3 bucket. The <code>putObjectToS3</code> function will return the object that was created in the S3 bucket.</p>
<p>The <code>putItemToDynamoDB</code> function will save the details to a DynamoDB table.</p>
<p>Now, let's deploy our application. We'll be using the <code>serverless</code> package to deploy our application. for this we need to write the <code>YAML</code> file containing all the details of resources and configuration of our application.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">service:</span> <span class="hljs-string">speak-polly-app</span>
<span class="hljs-attr">frameworkVersion:</span> <span class="hljs-string">'3'</span>

<span class="hljs-attr">custom:</span>
  <span class="hljs-attr">text_bucket:</span> <span class="hljs-string">text-${self:service}-${self:provider.stage}</span>
  <span class="hljs-attr">audio_bucket:</span> <span class="hljs-string">audio-${self:service}-${self:provider.stage}</span>
  <span class="hljs-attr">dynamodb_table:</span> <span class="hljs-string">mp3-${self:service}-${self:provider.stage}</span>

<span class="hljs-attr">provider:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">aws</span>
  <span class="hljs-attr">runtime:</span> <span class="hljs-string">nodejs14.x</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">dev</span>
  <span class="hljs-attr">region:</span> <span class="hljs-string">ap-south-1</span>
  <span class="hljs-attr">memorySize:</span> <span class="hljs-number">128</span>
  <span class="hljs-attr">timeout:</span> <span class="hljs-number">100</span>
  <span class="hljs-attr">profile:</span> <span class="hljs-string">serverless-admin</span>
  <span class="hljs-attr">environment:</span>
    <span class="hljs-attr">TEXT_BUCKET:</span> <span class="hljs-string">${self:custom.text_bucket}</span>
    <span class="hljs-attr">AUDIO_BUCKET:</span> <span class="hljs-string">${self:custom.audio_bucket}</span>
    <span class="hljs-attr">DYNAMODB_TABLE:</span> <span class="hljs-string">${self:custom.dynamodb_table}</span>

  <span class="hljs-attr">iam:</span>
    <span class="hljs-attr">role:</span>
      <span class="hljs-attr">statements:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">Effect:</span> <span class="hljs-string">Allow</span>
          <span class="hljs-attr">Action:</span> <span class="hljs-string">'s3:*'</span>
          <span class="hljs-attr">Resource:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'arn:aws:s3:::${self:custom.text_bucket}/*'</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'arn:aws:s3:::${self:custom.text_bucket}*'</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'arn:aws:s3:::${self:custom.audio_bucket}/*'</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'arn:aws:s3:::${self:custom.audio_bucket}*'</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">Effect:</span> <span class="hljs-string">Allow</span>
          <span class="hljs-attr">Action:</span> <span class="hljs-string">'polly:*'</span>
          <span class="hljs-attr">Resource:</span> <span class="hljs-string">'*'</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">Effect:</span> <span class="hljs-string">Allow</span>
          <span class="hljs-attr">Action:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'dynamodb:PutItem'</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'dynamodb:GetItem'</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'dynamodb:DeleteItem'</span>
          <span class="hljs-attr">Resource:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'arn:aws:dynamodb:${self:provider.region}:*:table/${self:custom.dynamodb_table}'</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'arn:aws:dynamodb:${self:provider.region}:*:table/${self:custom.dynamodb_table}/*'</span>

<span class="hljs-attr">functions:</span>
  <span class="hljs-attr">speakPolly:</span>
    <span class="hljs-attr">handler:</span> <span class="hljs-string">handler.speakPolly</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">VOICE_AGENT:</span> <span class="hljs-string">Joanna</span>

    <span class="hljs-attr">events:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">s3:</span>
          <span class="hljs-attr">bucket:</span> <span class="hljs-string">${self:custom.text_bucket}</span>
          <span class="hljs-attr">event:</span> <span class="hljs-string">s3:ObjectCreated:*</span>
          <span class="hljs-attr">rules:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-attr">prefix:</span> <span class="hljs-string">transcripts/</span>
            <span class="hljs-bullet">-</span> <span class="hljs-attr">suffix:</span> <span class="hljs-string">.txt</span>

<span class="hljs-comment"># you can add CloudFormation resource templates here</span>
<span class="hljs-attr">resources:</span>
  <span class="hljs-attr">Resources:</span>
    <span class="hljs-attr">S3AudioBucket:</span>
      <span class="hljs-attr">Type:</span> <span class="hljs-string">AWS::S3::Bucket</span>
      <span class="hljs-attr">Properties:</span>
        <span class="hljs-attr">BucketName:</span> <span class="hljs-string">${self:custom.audio_bucket}</span>
        <span class="hljs-attr">AccessControl:</span> <span class="hljs-string">PublicRead</span>
        <span class="hljs-attr">VersioningConfiguration:</span>
          <span class="hljs-attr">Status:</span> <span class="hljs-string">Suspended</span>

    <span class="hljs-attr">DynamoDBTable:</span>
      <span class="hljs-attr">Type:</span> <span class="hljs-string">AWS::DynamoDB::Table</span>
      <span class="hljs-attr">Properties:</span>
        <span class="hljs-attr">TableName:</span> <span class="hljs-string">${self:custom.dynamodb_table}</span>
        <span class="hljs-attr">AttributeDefinitions:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-attr">AttributeName:</span> <span class="hljs-string">id</span>
            <span class="hljs-attr">AttributeType:</span> <span class="hljs-string">S</span>
        <span class="hljs-attr">KeySchema:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-attr">AttributeName:</span> <span class="hljs-string">id</span>
            <span class="hljs-attr">KeyType:</span> <span class="hljs-string">HASH</span>
        <span class="hljs-attr">ProvisionedThroughput:</span>
          <span class="hljs-attr">ReadCapacityUnits:</span> <span class="hljs-number">1</span>
          <span class="hljs-attr">WriteCapacityUnits:</span> <span class="hljs-number">1</span>
</code></pre>
<h4 id="heading-lets-understand-the-yaml-file">Let's understand the <code>YAML</code> file.</h4>
<p>The <code>service</code> property is the name of our application. The <code>frameworkVersion</code> property is the version of the <code>serverless</code> package we are using.</p>
<p>The <code>custom</code> property is used to define the custom properties. We'll be using the <code>text_bucket</code> and <code>audio_bucket</code> and <code>dynamodb_table</code> properties to define the name of the S3 buckets and DynamoDB table we are going to create.</p>
<p>The <code>provider</code> property is used to define the provider of our application. We'll be using the <code>aws</code> provider. The <code>runtime</code> property is the runtime environment of our application. We'll be using the <code>nodejs14.x</code> runtime environment. The <code>stage</code> property is the stage of our application. We'll be using the <code>dev</code> stage. The <code>region</code> property is in which region our application and resources are going to reside. We'll be using the <code>ap-south-1</code> (Mumbai) region. The <code>memorySize</code> property is the memory size that the lambda function gets. We'll be using the <code>128 MB</code>. The <code>timeout</code> property is the maximum number of seconds that our function can run at a single invocation. We'll be using the <code>100</code> timeout. The <code>profile</code> property is the aws profile that I'm going to use. If you're using default or have a single account configured you can remove it. Here I'm using the <code>serverless-admin</code> profile. The <code>environment</code> property is the environment variables of our lambda function.</p>
<p>The <code>iam</code> property is used to define the IAM roles that our application going to need. The <code>role</code> property is used to define the IAM role of our application. The <code>statements</code> is used to define the IAM statements. The <code>Effect</code> property is used to define the effect of the IAM statement. The <code>action</code> property is used to define the action of the IAM statement. The <code>Resource</code> property is used to define the resources of the IAM statement.</p>
<p>The <code>functions</code> block defines the functions of our application. <code>speakPolly</code> is the function of our application, you can declare one or more functions as well. The <code>handler</code> property is used to define the handler function of the lambda function. The <code>environment</code> property is used to define the environment variables specific to the function. The <code>events</code> property is used to define the events that can trigger the function. The S3 event that is declared can trigger the <code>speakPolly</code> function.</p>
<p>The <code>resources</code> property is used to define the resources of our application. The <code>S3AudioBucket</code> is to define the S3 destination bucket. The <code>Type</code> property is used to define the type of resource. The <code>Properties</code> statement is used to define the different properties of the resource. Similarly, with the <code>DynamoDBTable</code> property a DynamoDB table and its different attributes are mentioned.</p>
<p>Now, let's deploy our application. We'll use the <code>serverless</code> package to deploy our application.</p>
<pre><code class="lang-bash">serverless deploy --verbose
</code></pre>
<blockquote>
<p>Note: Instead of <code>serverless</code> you can also use <code>sls</code>.</p>
</blockquote>
<p>The <code>serverless deploy</code> command will deploy our application. The <code>--verbose</code> flag will display the verbose output of the command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666275416511/tdSp-43Ul.png" alt="function-home.png" /></p>
<p>The command with the <code>serverless.yml</code> file will create a <code>cloudformation</code> stack. The cloudformation stack intern will create all the necessary IAM roles, S3 buckets, Lambda functions, database tables, and other required resources.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666275324591/cyJV_GSrY.png" alt="cloud-formation.png" /></p>
<p>After the deployment is completed, we'll get the details of the resources that were created.</p>
<p>Now you can upload the text file to the S3 TextBucket. The <code>speakPolly</code> function will be triggered. The <code>speakPolly</code> function will generate the speech from the text and put the audio stream into the S3 bucket. the metadata like audio filename, VoiceId, creation date, etc will be stored in dynamodb.</p>
<p>For every execution, a log stream will be created in the CloudWatch logs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666275223197/J9etu6B0p.png" alt="cloud-watch-logs.png" /></p>
<p>The output of the <code>speakPolly</code> function can be seen in the target S3 Bucket with the MP3 file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666275268409/YsyN-IKCn.png" alt="output-s3-mp3-file.png" /></p>
<h3 id="heading-cleanup">Cleanup</h3>
<p>After you test the application, you can remove the application by serverless to make sure you don't get charged for the resources that were created.</p>
<pre><code class="lang-bash">serverless remove --verbose
</code></pre>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.html">AWS SDK for JavaScript</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Polly.html">AWS SDK for JavaScript - Polly</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html">AWS SDK for JavaScript - S3</a></li>
<li><a target="_blank" href="https://www.serverless.com/">Serverless Framework</a></li>
<li><a target="_blank" href="https://www.serverless.com/framework/docs/providers/aws/">Serverless Framework - AWS Lambda</a></li>
<li><a target="_blank" href="https://www.serverless.com/framework/docs/providers/aws/guide/functions/">Serverless Framework - AWS Lambda - Functions</a></li>
<li><p><a target="_blank" href="https://aws.amazon.com/polly/">AWS Polly</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/ashutosh4336/speak-polly-serverless">https://github.com/ashutosh4336/speak-polly-serverless</a></div>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Send AWS EC2 Instance logs to CloudWatch.]]></title><description><![CDATA[One of the most important aspects of maintaining an application is resilience and quickly recovering from failover. In order to achieve this, we need to monitor the application and its components. AWS provides a service called CloudWatch which can be...]]></description><link>https://blog.thehttp.in/aws-ec2-logs-to-cloudwatch</link><guid isPermaLink="true">https://blog.thehttp.in/aws-ec2-logs-to-cloudwatch</guid><category><![CDATA[AWS]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[ec2]]></category><category><![CDATA[logging]]></category><dc:creator><![CDATA[Ashutosh Panda]]></dc:creator><pubDate>Wed, 19 Oct 2022 22:17:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666269715348/y86ZlOXjk.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the most important aspects of maintaining an application is resilience and quickly recovering from failover. In order to achieve this, we need to monitor the application and its components. AWS provides a service called CloudWatch which can be used to monitor the application and its components. <code>CloudWatch</code> can be used to monitor the application <code>logs</code>, <code>metrics</code>, and <code>alarms</code>. In this article, we will see how to send the EC2 instance's system logs to CloudWatch.</p>
<h2 id="heading-what-is-cloudwatch-and-why-do-we-need-it">What is Cloudwatch and why do we need it?</h2>
<p>CloudWatch is a monitoring and management service built for AWS cloud resources and the applications you run on AWS. CloudWatch provides you with data and actionable insights to monitor your applications, respond to system-wide performance changes, optimize resource utilization, and get a unified view of operational health. There are many more advantages of using CloudWatch. You can find them <a target="_blank" href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html">here</a>.</p>
<p>So without further ado, let's see how to send the application logs to CloudWatch.</p>
<h2 id="heading-steps">Steps</h2>
<h3 id="heading-create-iam-role">Create IAM Role.</h3>
<blockquote>
<p>Create IAM Role with relevant permission and attach it to the Linux instance.</p>
</blockquote>
<p>Below are the steps to create IAM Role.</p>
<p>Login to the AWS console, and go to the IAM service. Click on Roles in the sidebar and then click on Create Role.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666205492615/suOnMeNYQ.png" alt="IamDashBoard.png" /></p>
<p><br /></p>
<p>Select EC2 and click on Next to Permissions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666205525854/qfgzJQqrM.png" alt="create-role.png" /></p>
<p><br /></p>
<p>Add the permission. Here we are adding permission to send logs to CloudWatch. You can add more permissions as per your requirement.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666205556322/ardyhaa1p.png" alt="IAM-Role-EC2.png" /></p>
<p><br /></p>
<p>Click on Next: In the next screen you'll be presented with a screen to enter a name and tags and then click on Next: Review.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666205629086/Qo180_jcC.png" alt="name-and-review.png" /></p>
<p><br /></p>
<p>Click on Create Role.</p>
<p>It'll take you to the Roles page. You can see the role you just created. Click on the role name to see the details of the role.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666205647652/VGP4uxpE2.png" alt="IAM-Role.png" /></p>
<h3 id="heading-lunch-ec2-instance">Lunch EC2 Instance</h3>
<p>Launch an EC2 instance with default options which should be fine for this demo. please make sure you add a key pair to the instance through which you can <code>ssh</code> into the instance.</p>
<p>After the EC2 instance is up and running, we need to attach it to the EC2 Instance, go to EC2 service and select the instance. Click on Actions. Select the Linux instance and click on <code>Actions</code>. Select <code>security</code> and click on <code>Modify IAM role</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666205674543/v4_yphbWZ.png" alt="attaching-role.png" /></p>
<p>Select the IAM Role you just created from the dropdown and click on <code>Apply</code>.</p>
<h3 id="heading-configure-the-instance-to-send-logs">Configure the Instance to send logs.</h3>
<p>After attaching IAM Role to the Linux instance, install the CloudWatch agent on the Linux instance.</p>
<p>Login to the Linux instance and run the below command to install the CloudWatch agent.</p>
<pre><code class="lang-bash">sudo yum install -y awslogs
</code></pre>
<ul>
<li>Edit file <code>/etc/awslogs/awscli.conf</code> and change your AWS Region to the region in which instance is launched.</li>
</ul>
<pre><code class="lang-bash">sudo vi /etc/awslogs/awscli.conf
</code></pre>
<pre><code class="lang-conf">[plugins]
cwlogs = cwlogs
[default]
region = ap-south-1
</code></pre>
<ul>
<li>For creating a custom <code>Log Group</code> and other customization Edit file <code>/etc/awslogs/awslogs.conf</code>.</li>
</ul>
<pre><code class="lang-bash">sudo vi /etc/awslogs/awslogs.conf
</code></pre>
<ul>
<li>At the end of the file, add the following lines to configure the agent to send the logs to CloudWatch Logs.</li>
</ul>
<pre><code class="lang-conf">  [/var/log/messages]
  datetime_format = %b %d %H:%M:%S
  file = /var/log/messages
  buffer_duration = 5000
  log_stream_name = {instance_id}
  initial_position = start_of_file
  log_group_name = EC2Logs
</code></pre>
<ul>
<li>Start and enable <code>awslogsd</code> service by typing the command.</li>
</ul>
<pre><code class="lang-bash">  sudo systemctl start awslogsd
</code></pre>
<pre><code class="lang-bash">  sudo systemctl <span class="hljs-built_in">enable</span> awslogsd
</code></pre>
<ul>
<li>To verify that the agent is running, type the following command. (optional)</li>
</ul>
<pre><code class="lang-bash">  sudo systemctl status awslogsd
</code></pre>
<p>You should see the newly created log group and log stream in the CloudWatch console after the agent has been running for a few moments.</p>
<p>The Log Group name is <code>EC2Logs</code> and the Log Stream name is the instance ID of the EC2 instance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666205701833/lgKEI_oUD.png" alt="cloudwatch-logs.png" /></p>
<p><br /></p>
<p>If you're not sure and want to install the AWS SSM Agent while lunching</p>
<p>Add these lines to your user data</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
sudo yum update -y
sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
</code></pre>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.html">AWS Docs</a></li>
</ul>
]]></content:encoded></item></channel></rss>