<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Valeriane Venance, Author at Clever Cloud</title>
	<atom:link href="https://www.clever.cloud/blog/author/vvenance/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>From Code to Product</description>
	<lastBuildDate>Thu, 27 Nov 2025 15:21:31 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://cdn.clever-cloud.com/uploads/2023/03/cropped-cropped-favicon-32x32.png</url>
	<title>Valeriane Venance, Author at Clever Cloud</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to Deploy your Elixir/Phoenix Application to Production</title>
		<link>https://www.clever.cloud/blog/engineering/2020/06/09/deploy-elixir-phoenix/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Tue, 09 Jun 2020 10:40:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[elixir]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[phoenix]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/06/09/deploy-elixir-phoenix/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="phoenix 1" decoding="async" fetchpriority="high" srcset="https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p>Hi everyone! Today let's follow a simple deployment tutorial to learn how to deploy your Elixir/Phoenix Application.

<span id="more-2828"></span>
<h2 id="step-1-creating-a-new-phoenix-application">Step 1: Creating a new Phoenix Application</h2>
If you follow this tutorial, I assume you already have Elixir and Phoenix's dependencies installed locally. If you don't, you will probably want to read <a href="https://hexdocs.pm/phoenix/installation.html">this tutorial</a>.

To create a brand-new Phoenix application locally, we just need to type in our terminal:
<pre><code class="language-bash">$ mix phx.new &lt;your application's name&gt; # creating the new phoenix project
$ cd &lt;your application's name&gt;
$ mix ecto.create # creating database locally
</code></pre>
Creating the database locally isn't crucial for this tutorial, but it can help if you want to code on your machine.
<h3 id="note-to-osx-users">Note to OSX users</h3>
If you use OSX like me, you may encounter this error: <code>(Postgrex.Error) FATAL 28000 (invalid_authorization_specification) role "postgres" does not exist</code>. This is because when installing PostgreSQL with brew, it creates a user with your short name, not <code>postgres</code>. To fix this, open the project with your favorite text editor and replace <code>username: "postgres",</code> by <code>username: "&lt;your name&gt;",</code> in the file <code>config/dev.exs</code>. For instance, my name is <code>valeriane venance</code> in my computer so I replace with <code>username: "valeriane",</code>.
<h2 id="step-2-getting-our-application-ready-for-production">Step 2: Getting your Application Ready for Production</h2>
From the code perspective, all we need to do is to edit <code>config/prod.secret.exs</code> to replace <code>System.get_env("DATABASE_URL")</code> with <code>System.get_env("POSTGRESQL_ADDON_URI")</code>. This is because we will use the PostgreSQL add-on environment variable provided by Clever Cloud to your application instead of the default value.

Back in our terminal, we will generate a secret token that we will save for later with <code>$ mix phx.gen.secret</code> and check our elixir version with <code>$ elixir -v</code>.

And that's it. Easy right? Now let's go into our <a href="https://console.clever-cloud.com" target="_blank" rel="noopener">Clever Cloud console</a>.
<h2 id="step-3-creating-the-prod-application-and-database">Step 3: Creating the Prod Application and Database</h2>
If you already are a Clever Cloud user, these steps must be really familiar to you:
<ul>
 	<li>Under the organization of your choice, click new, then application. Select <strong>Elixir</strong>, then name your application and choose its deployment zone.</li>
 	<li>When prompted if you need an add-on, select <strong>PostgreSQL</strong>. Select your database size and name it.</li>
 	<li>On the environment variable screen create two new ones:</li>
 	<li><strong>SECRET_KEY_BASE</strong> with the value obtained from <code>$ mix phx.gen.secret</code> previously</li>
 	<li><strong>CC_ELIXIR_VERSION</strong> with the value of <code>$ elixir -v</code> result. (Available values as of today are <code>1.8</code>, <code>1.9</code> or <code>1.10</code>)</li>
 	<li>Click on <strong>update changes</strong></li>
 	<li>Bonus: if you have migrations to run you could also set the environment variable <strong>CC_PHOENIX_RUN_ECTO_MIGRATE</strong> to <code>true</code> to trigger the command <code>$ mix ecto.migrate</code></li>
</ul>
<h2 id="step-4-deploy">Step 4: deploy!</h2>
Once the previous steps are made, Clever Cloud will provide you a git remote and the commands to add the remote and to push your code. If you had not done it before, initialize a new git repository in your terminal with <code>git init</code>. Then add and commit your code. Now you should be able to copy and paste the provided git commands. If you go back to your Clever Cloud console, you will see that your deployment has started and logs should show up. Wait a few moments and your application will be up and running. You can visit it by clicking the link icon on top of your application's menu in the Clever Cloud console.
<h2 id="the-magic-explained">The magic explained</h2>
As Phoenix is a framework that was built to be as easy to use as RubyOnRails but less <em>magical</em>, let's demystify what just happened here.

When we push our code to the remote Clever Cloud provided, the following commands are run:
<pre><code class="language-bash">$ mix deps.get
$ mix deps.compile
$ npm install
</code></pre>
These commands will compile your dependencies at the root of your project folder. If you want to use another folder for <code>npm install</code>, specify it via the environment variable <strong>CC_PHOENIX_ASSETS_DIR</strong>. To change the folder for the entire build/run process, you should use the <strong>APP_FOLDER</strong> environment variable.

Then <code>$ mix compile</code> is run. If you want to override this behavior, you can set the environment variable <strong>CC_MIX_BUILD_GOAL</strong> to the value you desire.

At this point, there is the command <code>$ npm run deploy</code>.

Then <code>$ mix phx.digest</code> is run. You can override this one with the variable <strong>CC_PHOENIX_DIGEST_GOAL</strong>.

Finally, <code>$ mix phx.server</code> is invoked, and as always, you can override this behavior, either with <strong>CC_RUN_COMMAND</strong> where you have to specify the full command, or <strong>CC_PHOENIX_SERVER_GOAL</strong> where it will be a mix task by default.

If you need to specify the time zone of your application, you can do it with the variable <strong>TZ</strong> set to the usual time zone format, for instance <code>Europe/Paris</code>.

And that's it really, now you know how to deploy your Elixir/Phoenix Application. All you have to do left is write code, commit and push it again! Happy hacking!]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="phoenix 1" decoding="async" srcset="https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/phoenix-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p>Hi everyone! Today let's follow a simple deployment tutorial to learn how to deploy your Elixir/Phoenix Application.

<span id="more-2828"></span>
<h2 id="step-1-creating-a-new-phoenix-application">Step 1: Creating a new Phoenix Application</h2>
If you follow this tutorial, I assume you already have Elixir and Phoenix's dependencies installed locally. If you don't, you will probably want to read <a href="https://hexdocs.pm/phoenix/installation.html">this tutorial</a>.

To create a brand-new Phoenix application locally, we just need to type in our terminal:
<pre><code class="language-bash">$ mix phx.new &lt;your application's name&gt; # creating the new phoenix project
$ cd &lt;your application's name&gt;
$ mix ecto.create # creating database locally
</code></pre>
Creating the database locally isn't crucial for this tutorial, but it can help if you want to code on your machine.
<h3 id="note-to-osx-users">Note to OSX users</h3>
If you use OSX like me, you may encounter this error: <code>(Postgrex.Error) FATAL 28000 (invalid_authorization_specification) role "postgres" does not exist</code>. This is because when installing PostgreSQL with brew, it creates a user with your short name, not <code>postgres</code>. To fix this, open the project with your favorite text editor and replace <code>username: "postgres",</code> by <code>username: "&lt;your name&gt;",</code> in the file <code>config/dev.exs</code>. For instance, my name is <code>valeriane venance</code> in my computer so I replace with <code>username: "valeriane",</code>.
<h2 id="step-2-getting-our-application-ready-for-production">Step 2: Getting your Application Ready for Production</h2>
From the code perspective, all we need to do is to edit <code>config/prod.secret.exs</code> to replace <code>System.get_env("DATABASE_URL")</code> with <code>System.get_env("POSTGRESQL_ADDON_URI")</code>. This is because we will use the PostgreSQL add-on environment variable provided by Clever Cloud to your application instead of the default value.

Back in our terminal, we will generate a secret token that we will save for later with <code>$ mix phx.gen.secret</code> and check our elixir version with <code>$ elixir -v</code>.

And that's it. Easy right? Now let's go into our <a href="https://console.clever-cloud.com" target="_blank" rel="noopener">Clever Cloud console</a>.
<h2 id="step-3-creating-the-prod-application-and-database">Step 3: Creating the Prod Application and Database</h2>
If you already are a Clever Cloud user, these steps must be really familiar to you:
<ul>
 	<li>Under the organization of your choice, click new, then application. Select <strong>Elixir</strong>, then name your application and choose its deployment zone.</li>
 	<li>When prompted if you need an add-on, select <strong>PostgreSQL</strong>. Select your database size and name it.</li>
 	<li>On the environment variable screen create two new ones:</li>
 	<li><strong>SECRET_KEY_BASE</strong> with the value obtained from <code>$ mix phx.gen.secret</code> previously</li>
 	<li><strong>CC_ELIXIR_VERSION</strong> with the value of <code>$ elixir -v</code> result. (Available values as of today are <code>1.8</code>, <code>1.9</code> or <code>1.10</code>)</li>
 	<li>Click on <strong>update changes</strong></li>
 	<li>Bonus: if you have migrations to run you could also set the environment variable <strong>CC_PHOENIX_RUN_ECTO_MIGRATE</strong> to <code>true</code> to trigger the command <code>$ mix ecto.migrate</code></li>
</ul>
<h2 id="step-4-deploy">Step 4: deploy!</h2>
Once the previous steps are made, Clever Cloud will provide you a git remote and the commands to add the remote and to push your code. If you had not done it before, initialize a new git repository in your terminal with <code>git init</code>. Then add and commit your code. Now you should be able to copy and paste the provided git commands. If you go back to your Clever Cloud console, you will see that your deployment has started and logs should show up. Wait a few moments and your application will be up and running. You can visit it by clicking the link icon on top of your application's menu in the Clever Cloud console.
<h2 id="the-magic-explained">The magic explained</h2>
As Phoenix is a framework that was built to be as easy to use as RubyOnRails but less <em>magical</em>, let's demystify what just happened here.

When we push our code to the remote Clever Cloud provided, the following commands are run:
<pre><code class="language-bash">$ mix deps.get
$ mix deps.compile
$ npm install
</code></pre>
These commands will compile your dependencies at the root of your project folder. If you want to use another folder for <code>npm install</code>, specify it via the environment variable <strong>CC_PHOENIX_ASSETS_DIR</strong>. To change the folder for the entire build/run process, you should use the <strong>APP_FOLDER</strong> environment variable.

Then <code>$ mix compile</code> is run. If you want to override this behavior, you can set the environment variable <strong>CC_MIX_BUILD_GOAL</strong> to the value you desire.

At this point, there is the command <code>$ npm run deploy</code>.

Then <code>$ mix phx.digest</code> is run. You can override this one with the variable <strong>CC_PHOENIX_DIGEST_GOAL</strong>.

Finally, <code>$ mix phx.server</code> is invoked, and as always, you can override this behavior, either with <strong>CC_RUN_COMMAND</strong> where you have to specify the full command, or <strong>CC_PHOENIX_SERVER_GOAL</strong> where it will be a mix task by default.

If you need to specify the time zone of your application, you can do it with the variable <strong>TZ</strong> set to the usual time zone format, for instance <code>Europe/Paris</code>.

And that's it really, now you know how to deploy your Elixir/Phoenix Application. All you have to do left is write code, commit and push it again! Happy hacking!]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Force HTTPS on Clever Cloud applications</title>
		<link>https://www.clever.cloud/blog/features/2020/06/02/force-https/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Tue, 02 Jun 2020 17:41:00 +0000</pubDate>
				<category><![CDATA[Features]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[HTTPS]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/06/02/force-https/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="bannerhttps 1" decoding="async" srcset="https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>It is now possible to force HTTPS redirection! No more .htaccess black magic, no redirection handling code…  Let&#39;s have a tour of this new feature.</p>
<span id="more-2975"></span>

<h2 id="forcing-https-on-clever-cloud">Forcing HTTPS on Clever Cloud</h2>
<p>Let&#39;s start practical. There are two ways to achieve our goal.</p>
<h3 id="using-the-cli">Using the CLI</h3>
<p>In your linked application, in your own terminal just type in <code>clever config set force-https enabled</code>.</p>
<p><code>clever config</code> is a new CLI command that allows you to display in your console the current configuration of your application. You can edit any setting with <code>clever config set {name} {value}</code> and bulk edit with <code>clever config update [options]</code>.</p>
<p>Here we just set the force https option to <strong>enabled</strong> and if we want to set if off we can just <code>clever config set force-https disabled</code>.</p>
<p>If this does not work for you, make sure you are running version 2.5.0 or newer (with <code>clever version</code>).</p>
<h3 id="using-the-clever-cloud-console">Using the Clever Cloud console</h3>
<p>In the information page of each application, you will find a checkbox form with options you can tune in and out. One of them is <strong>Force HTTPS</strong>. Enable its checkbox and save.</p>
<figure>
  <a href="https://cdn.clever-cloud.com/uploads/2021/08/enable-https.png" rel="noopener noreferrer" target="_blank"><img style="width:100%" src="https://cdn.clever-cloud.com/uploads/2021/08/enable-https.png"></a>
</figure>

<p>From now on and as long as you do not disable it, every non-secured HTTP request to this application will be redirected to HTTPS with a <a href="https://en.wikipedia.org/wiki/HTTP_301">301 Moved Permanently</a> status code.</p>
<h2 id="how-the-magic-happens">How the magic happens</h2>
<h3 id="the-clever-cloud-way">The Clever Cloud way</h3>
<p>The redirection is handled at the reverse proxy level so you don&#39;t need to update your application to use it. Each time the browser will request a resource using HTTP, it will get a 301 response back with the same resource prefixed by <code>https</code> in the Location header field. The 301 redirection is recognized as the best practice for HTTPS upgrade.</p>
<figure>
  <a href="https://cdn.clever-cloud.com/uploads/2021/08/force-https-schema.png" rel="noopener noreferrer" target="_blank"><img style="width:100%" src="https://cdn.clever-cloud.com/uploads/2021/08/force-https-schema.png"></a>
</figure>

<h2 id="why-enforce-https">Why enforce HTTPS</h2>
<p>Before explaining why it is important, I shall provide a definition of HTTPS.</p>
<h3 id="simple-definition">Simple definition</h3>
<p>First of all, HTTPS is an extension of the HTTP protocol. Which itself is the application protocol the world wide web is relying on for communications. Full definition to be found on <a href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">wikipedia</a>.</p>
<p>The main difference between HTTP and HTTPS communication is encryption.</p>
<p>Using HTTPS, the communication is bidirectionaly encrypted between the client and the server. Both the headers and the response/request data are ciphered. This is achieved using TLS cryptographic protocol in addition to operations involved in a simple HTTP transmission.</p>
<p>The identification process requires the server administrator to create a public key certificate signed by a trusted certificate authority.</p>
<p>We have automated this part. So every time you create a new application on Clever Cloud, a cleverapps.io subdomain name is given to your application and comes along with encryption because a certificate covers cleverapps.io and all its subdomains. And each time you add a custom domain to your application like <code>example.com</code>, Clever Cloud asks Let&#39;s Encrypt for a TLS public key certificate that we automatically add to your application&#39;s configuration on our reverse proxies. Thanks to that, you can accept HTTPS requests on a brand new application without further configuration.</p>
<h3 id="enforcing-https-is-just-the-beginning">Enforcing HTTPS is just the beginning</h3>
<p>I explained to you how HTTPS enforcing was working on Clever Cloud and that felt very simple, right?</p>
<p>To be honest this is because the tech team has decided only to handle the first step of the process.</p>
<p>Strong security on an application requires knowledge on many topics.</p>
<p>Sometimes, your application itself will link to HTTP content, which will result in <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content">mixed-content</a>. When HTTP resources are served by the application on a page requested using HTTPS the browser will usually not load those resources.</p>
<p>You will also probably want to know more about HTTP Strict Transport Security (HSTS), and the <code>Content-Security-Policy</code> header.</p>
<p>You can start by reading <a href="https://scotthelme.co.uk/migrating-from-http-to-https-ease-the-pain-with-csp-and-hsts/">this great article from Scott Helme</a> to start your journey. If you cannot handle advanced security yourself, think about asking for the help of a security expert.</p>
<h2 id="https-is-good-for-everyone-except-hackers">HTTPS is good for everyone, except hackers</h2>
<p>In 2020 the HTTPS protocol is ubiquitous. It&#39;s more and more widely used thanks to the <a href="https://letsencrypt.org/">Let&#39;s Encrypt</a> initiative which made it free for everyone; which makes the web more secure for both applications creators and clients.</p>
<p>The clients know they can trust the integrity of the content that&#39;s being displayed to them and feel safer about using the Internet in general. This safety feeling extends to their privacy. Today the regular user&#39;s main concern is about what the owner of the website do with their data. Not about that black hooded bad guy they were freaking out about a few years ago. The most used websites have raised their confidence about communications ciphering to such a level it&#39;s now the norm. Everyone puts credit-card numbers in forms eyes wide shut.</p>
<p>Yeah, but me ? Having a website to offer to the world, I want to meet my client’s expectations, of course. But HTTPS has more to offer me. From the SEO perspective, having it will naturally boost ranking. I also ensure my user&#39;s privacy and confidentiality. Most importantly, I can trust that the data I receive from my client has not been altered. That doesn’t mean that I shall trust my user intentions obviously. But now if I need to watch out for a hacker, it will not come from a <a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">man in the middle</a> or this kind of attack.</p>
<p>Anyway, this is everywhere now and already almost mandatory. Take this train now! This feature is free, does not require extra code and works out of the box with the automatically generated Let&#39;s Encrypt certificates.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="bannerhttps 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/bannerhttps-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>It is now possible to force HTTPS redirection! No more .htaccess black magic, no redirection handling code…  Let&#39;s have a tour of this new feature.</p>
<span id="more-2975"></span>

<h2 id="forcing-https-on-clever-cloud">Forcing HTTPS on Clever Cloud</h2>
<p>Let&#39;s start practical. There are two ways to achieve our goal.</p>
<h3 id="using-the-cli">Using the CLI</h3>
<p>In your linked application, in your own terminal just type in <code>clever config set force-https enabled</code>.</p>
<p><code>clever config</code> is a new CLI command that allows you to display in your console the current configuration of your application. You can edit any setting with <code>clever config set {name} {value}</code> and bulk edit with <code>clever config update [options]</code>.</p>
<p>Here we just set the force https option to <strong>enabled</strong> and if we want to set if off we can just <code>clever config set force-https disabled</code>.</p>
<p>If this does not work for you, make sure you are running version 2.5.0 or newer (with <code>clever version</code>).</p>
<h3 id="using-the-clever-cloud-console">Using the Clever Cloud console</h3>
<p>In the information page of each application, you will find a checkbox form with options you can tune in and out. One of them is <strong>Force HTTPS</strong>. Enable its checkbox and save.</p>
<figure>
  <a href="https://cdn.clever-cloud.com/uploads/2021/08/enable-https.png" rel="noopener noreferrer" target="_blank"><img style="width:100%" src="https://cdn.clever-cloud.com/uploads/2021/08/enable-https.png"></a>
</figure>

<p>From now on and as long as you do not disable it, every non-secured HTTP request to this application will be redirected to HTTPS with a <a href="https://en.wikipedia.org/wiki/HTTP_301">301 Moved Permanently</a> status code.</p>
<h2 id="how-the-magic-happens">How the magic happens</h2>
<h3 id="the-clever-cloud-way">The Clever Cloud way</h3>
<p>The redirection is handled at the reverse proxy level so you don&#39;t need to update your application to use it. Each time the browser will request a resource using HTTP, it will get a 301 response back with the same resource prefixed by <code>https</code> in the Location header field. The 301 redirection is recognized as the best practice for HTTPS upgrade.</p>
<figure>
  <a href="https://cdn.clever-cloud.com/uploads/2021/08/force-https-schema.png" rel="noopener noreferrer" target="_blank"><img style="width:100%" src="https://cdn.clever-cloud.com/uploads/2021/08/force-https-schema.png"></a>
</figure>

<h2 id="why-enforce-https">Why enforce HTTPS</h2>
<p>Before explaining why it is important, I shall provide a definition of HTTPS.</p>
<h3 id="simple-definition">Simple definition</h3>
<p>First of all, HTTPS is an extension of the HTTP protocol. Which itself is the application protocol the world wide web is relying on for communications. Full definition to be found on <a href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">wikipedia</a>.</p>
<p>The main difference between HTTP and HTTPS communication is encryption.</p>
<p>Using HTTPS, the communication is bidirectionaly encrypted between the client and the server. Both the headers and the response/request data are ciphered. This is achieved using TLS cryptographic protocol in addition to operations involved in a simple HTTP transmission.</p>
<p>The identification process requires the server administrator to create a public key certificate signed by a trusted certificate authority.</p>
<p>We have automated this part. So every time you create a new application on Clever Cloud, a cleverapps.io subdomain name is given to your application and comes along with encryption because a certificate covers cleverapps.io and all its subdomains. And each time you add a custom domain to your application like <code>example.com</code>, Clever Cloud asks Let&#39;s Encrypt for a TLS public key certificate that we automatically add to your application&#39;s configuration on our reverse proxies. Thanks to that, you can accept HTTPS requests on a brand new application without further configuration.</p>
<h3 id="enforcing-https-is-just-the-beginning">Enforcing HTTPS is just the beginning</h3>
<p>I explained to you how HTTPS enforcing was working on Clever Cloud and that felt very simple, right?</p>
<p>To be honest this is because the tech team has decided only to handle the first step of the process.</p>
<p>Strong security on an application requires knowledge on many topics.</p>
<p>Sometimes, your application itself will link to HTTP content, which will result in <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content">mixed-content</a>. When HTTP resources are served by the application on a page requested using HTTPS the browser will usually not load those resources.</p>
<p>You will also probably want to know more about HTTP Strict Transport Security (HSTS), and the <code>Content-Security-Policy</code> header.</p>
<p>You can start by reading <a href="https://scotthelme.co.uk/migrating-from-http-to-https-ease-the-pain-with-csp-and-hsts/">this great article from Scott Helme</a> to start your journey. If you cannot handle advanced security yourself, think about asking for the help of a security expert.</p>
<h2 id="https-is-good-for-everyone-except-hackers">HTTPS is good for everyone, except hackers</h2>
<p>In 2020 the HTTPS protocol is ubiquitous. It&#39;s more and more widely used thanks to the <a href="https://letsencrypt.org/">Let&#39;s Encrypt</a> initiative which made it free for everyone; which makes the web more secure for both applications creators and clients.</p>
<p>The clients know they can trust the integrity of the content that&#39;s being displayed to them and feel safer about using the Internet in general. This safety feeling extends to their privacy. Today the regular user&#39;s main concern is about what the owner of the website do with their data. Not about that black hooded bad guy they were freaking out about a few years ago. The most used websites have raised their confidence about communications ciphering to such a level it&#39;s now the norm. Everyone puts credit-card numbers in forms eyes wide shut.</p>
<p>Yeah, but me ? Having a website to offer to the world, I want to meet my client’s expectations, of course. But HTTPS has more to offer me. From the SEO perspective, having it will naturally boost ranking. I also ensure my user&#39;s privacy and confidentiality. Most importantly, I can trust that the data I receive from my client has not been altered. That doesn’t mean that I shall trust my user intentions obviously. But now if I need to watch out for a hacker, it will not come from a <a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">man in the middle</a> or this kind of attack.</p>
<p>Anyway, this is everywhere now and already almost mandatory. Take this train now! This feature is free, does not require extra code and works out of the box with the automatically generated Let&#39;s Encrypt certificates.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Cellar a S3-like service for Rails&#8217; Active Storage</title>
		<link>https://www.clever.cloud/blog/engineering/2020/05/28/cellar-s3-active-storage-ruby-on-rails/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Thu, 28 May 2020 14:20:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[active storage]]></category>
		<category><![CDATA[cellar]]></category>
		<category><![CDATA[rails attachments]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/05/28/cellar-s3-active-storage-ruby-on-rails/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="railsbanner 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>Introduced with the release of Rails 5.2 , Active Storage replaces previous solutions for storing user videos, images, PDF, etc..</p>
<p>In the documentation only three implementations are demonstrated and they all rely on cloud services. Today I am going to show you how to use it to be Clever Cloud compatible.</p>
<span id="more-2827"></span>
<p>To follow this tutorial you must already have a Rails &gt;= 5.2 application running on Clever Cloud with a PostgreSQL database. You can <a href="https://www.clever.cloud/blog/engineering/2019/05/07/setup-your-ruby-on-rails-online-dev-environment/">read this</a> if you need a basic setup.</p>
<h2 id="tell-rails-you-want-to-use-active-storage">Tell Rails you want to use Active Storage</h2>
<p>In your console, at the root of your rails project repository, type in <code>$ rails active_storage:install</code>. This will create two migration files under <code>./db/migrate</code>. These migrations will create two new tables: <code>active_storage_blobs</code> and <code>active_storage_attachments</code>, which is everything we need to start storing user attachments without adding new columns to our already existent models. Let&#39;s run them with <code>$ rake db:migrate</code> to have a local database up to date. You can now use <code>has_one_attached :&lt;the name you want to give&gt;</code> on any of your models to add an attachment on it.</p>
<h2 id="setting-up-the-application-for-clever-cloud">Setting up the application for Clever Cloud</h2>
<p>As we do provide AWS S3 like storage at Clever Cloud, we will use AWS gem and define custom endpoints. Add <code>gem &quot;aws-sdk-s3&quot;, require: false</code> to your Gemfile. Run <code>$ bundle install</code>. Then in <code>config/environments/production.yml</code> add <code>config.active_storage.service = :clevercloud</code>. Now in <code>config/storage.yml</code> add the following lines:</p>
<pre><code class="language-yaml">clevercloud:
  service: S3
  access_key_id: &lt;%= ENV[&#39;CELLAR_ADDON_KEY_ID&#39;] %&gt;
  secret_access_key: &lt;%= ENV[&#39;CELLAR_ADDON_KEY_SECRET&#39;] %&gt;
  region: us-east-1
  bucket: &lt;%= ENV[&#39;CELLAR_ADDON_BUCKET_NAME&#39;] %&gt;
  endpoint: &lt;%= ENV[&#39;CELLAR_ADDON_ENDPOINT&#39;] %&gt;
</code></pre>
<p>I must make clear here that we do not use regions at Clever Cloud, but the aws-sdk-s3 gem needs it; otherwise it throws an <code>AWS::Errors::MissingRegionError</code> error. And we do not want a 500 in production. It is the usage of <code>endpoint</code> that will give us the right endpoint generated by the gem.</p>
<h2 id="creating-our-storage-on-clever-cloud">Creating our storage on Clever Cloud</h2>
<p>Under the organization where your Rails application is deployed, select <strong>Create</strong>, <strong>an add-on</strong>, <strong>Cellar S3 storage</strong>. When prompted <strong>Select the applications that will use this add-on:</strong> select your Rails application. Name it and let it be deployed. Once this is done, in your <strong>addon dashboard</strong>, create a bucket. Keep its name. Now, under <strong>Environment variables</strong> in your Rails application, add the following:</p>
<pre><code class="language-bash">CELLAR_ADDON_BUCKET_NAME=&lt;your bucket name&gt;
CELLAR_ADDON_ENDPOINT=https://cellar-c2.services.clever-cloud.com
</code></pre>
<p>You can now commit the local files we have changed and push them to your Clever Cloud remote to enjoy Active Storage in production.</p>
<p>Do not forget to edit your safe params in your controllers, forms and permissions.</p>
<p>Happy storing!</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="railsbanner 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/railsbanner-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>Introduced with the release of Rails 5.2 , Active Storage replaces previous solutions for storing user videos, images, PDF, etc..</p>
<p>In the documentation only three implementations are demonstrated and they all rely on cloud services. Today I am going to show you how to use it to be Clever Cloud compatible.</p>
<span id="more-2827"></span>
<p>To follow this tutorial you must already have a Rails &gt;= 5.2 application running on Clever Cloud with a PostgreSQL database. You can <a href="https://www.clever.cloud/blog/engineering/2019/05/07/setup-your-ruby-on-rails-online-dev-environment/">read this</a> if you need a basic setup.</p>
<h2 id="tell-rails-you-want-to-use-active-storage">Tell Rails you want to use Active Storage</h2>
<p>In your console, at the root of your rails project repository, type in <code>$ rails active_storage:install</code>. This will create two migration files under <code>./db/migrate</code>. These migrations will create two new tables: <code>active_storage_blobs</code> and <code>active_storage_attachments</code>, which is everything we need to start storing user attachments without adding new columns to our already existent models. Let&#39;s run them with <code>$ rake db:migrate</code> to have a local database up to date. You can now use <code>has_one_attached :&lt;the name you want to give&gt;</code> on any of your models to add an attachment on it.</p>
<h2 id="setting-up-the-application-for-clever-cloud">Setting up the application for Clever Cloud</h2>
<p>As we do provide AWS S3 like storage at Clever Cloud, we will use AWS gem and define custom endpoints. Add <code>gem &quot;aws-sdk-s3&quot;, require: false</code> to your Gemfile. Run <code>$ bundle install</code>. Then in <code>config/environments/production.yml</code> add <code>config.active_storage.service = :clevercloud</code>. Now in <code>config/storage.yml</code> add the following lines:</p>
<pre><code class="language-yaml">clevercloud:
  service: S3
  access_key_id: &lt;%= ENV[&#39;CELLAR_ADDON_KEY_ID&#39;] %&gt;
  secret_access_key: &lt;%= ENV[&#39;CELLAR_ADDON_KEY_SECRET&#39;] %&gt;
  region: us-east-1
  bucket: &lt;%= ENV[&#39;CELLAR_ADDON_BUCKET_NAME&#39;] %&gt;
  endpoint: &lt;%= ENV[&#39;CELLAR_ADDON_ENDPOINT&#39;] %&gt;
</code></pre>
<p>I must make clear here that we do not use regions at Clever Cloud, but the aws-sdk-s3 gem needs it; otherwise it throws an <code>AWS::Errors::MissingRegionError</code> error. And we do not want a 500 in production. It is the usage of <code>endpoint</code> that will give us the right endpoint generated by the gem.</p>
<h2 id="creating-our-storage-on-clever-cloud">Creating our storage on Clever Cloud</h2>
<p>Under the organization where your Rails application is deployed, select <strong>Create</strong>, <strong>an add-on</strong>, <strong>Cellar S3 storage</strong>. When prompted <strong>Select the applications that will use this add-on:</strong> select your Rails application. Name it and let it be deployed. Once this is done, in your <strong>addon dashboard</strong>, create a bucket. Keep its name. Now, under <strong>Environment variables</strong> in your Rails application, add the following:</p>
<pre><code class="language-bash">CELLAR_ADDON_BUCKET_NAME=&lt;your bucket name&gt;
CELLAR_ADDON_ENDPOINT=https://cellar-c2.services.clever-cloud.com
</code></pre>
<p>You can now commit the local files we have changed and push them to your Clever Cloud remote to enjoy Active Storage in production.</p>
<p>Do not forget to edit your safe params in your controllers, forms and permissions.</p>
<p>Happy storing!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Integrate Metabase in Ruby on Rails</title>
		<link>https://www.clever.cloud/blog/engineering/2020/05/14/metabase-integration-ruby-rails/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Thu, 14 May 2020 14:46:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[dashboard]]></category>
		<category><![CDATA[integration]]></category>
		<category><![CDATA[metabase]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/05/14/metabase-integration-ruby-rails/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="metabasebanner 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>Today, I am  proposing a very simple tutorial. I needed to integrate a Metabase dashboard in one of my applications and I realized there is no article which explains how to do that. So, ta-da!</p>
<span id="more-2825"></span>

<h2 id="requirements">Requirements</h2>
<p>To follow this tutorial, you will need</p>
<ul>
<li>a Metabase dashboard (read <a href="https://www.clever.cloud/blog/engineering/2019/02/20/how-to-install-metabase/">this article</a> from my fellow Laurent Dogin to have yours set up in a few minutes)</li>
<li>a Ruby on Rails application (read <a href="https://www.clever.cloud/blog/engineering/2019/05/07/setup-your-ruby-on-rails-online-dev-environment/">this article</a> by me if you need to set up one)</li>
</ul>
<h2 id="enabling-integration-in-metabase">Enabling integration in Metabase</h2>
<p>From your Metabase, click on the top right <strong>gear icon</strong>, then <strong>Admin</strong>. On the left menu select <strong>Embedding in other Applications</strong>. Toggle the button to have it saying <strong>Enabled</strong>. You will now get an Embedding API key. Save it for later.</p>
<figure style="position:relative;width:100%;height:auto;margin:0 auto">
  <img data-action="zoom"  alt="Enable integrations on Metabase" src="https://cdn.clever-cloud.com/uploads/2021/08/metabase-integration-screenshot.png"/>
</figure>

<p>Leave Metabase admin and select the dashboard you want to integrate. Click the sharing and embedding icon on the top right of your dashboard. Now select <strong>Embed this dashboard in an Application</strong>. Finally, click on the <strong>Publish</strong> button.</p>
<h2 id="integrate-metabase-in-rails">Integrate Metabase in Rails</h2>
<p>In your Gemfile, add <code>gem &#39;jwt&#39;</code> then run <code>$ bundle install</code>. If your application is deployed on Clever Cloud go to your application&#39;s console and under your application&#39;s menu go to the <strong>environment variables</strong> menu. If you deploy locally, use the <a href="https://github.com/laserlemon/figaro">gem figaro</a> and edit your application.yml. Anyway you must add two environment variables</p>
<pre><code class="language-yaml">METABASE_SITE_URL: &lt;your metabase url&gt;
METABASE_SECRET_KEY: &lt;the API key from metabase admin&gt;
</code></pre>
<p>In the controller action where you want to integrate your metabase dashboard, add the following lines:</p>
<pre><code class="language-ruby">payload = {
          :resource =&gt; {:dashboard =&gt; &lt;your dashboard number&gt;},
          :params =&gt; { },
          :exp =&gt; Time.now.to_i + (60 * 10) # 10 minute expiration
    }
token = JWT.encode(payload, ENV[&quot;METABASE_SECRET_KEY&quot;])
@iframe_url = ENV[&quot;METABASE_SITE_URL&quot;] + &quot;/embed/dashboard/&quot; + token + &quot;#bordered=true&amp;titled=true&quot;
</code></pre>
<p>Now in your view, add</p>
<pre><code class="language-html">&lt;iframe
    src=&quot;&lt;%= @iframe_url %&gt;&quot;
    frameborder=&quot;0&quot;
    width=&quot;800&quot;
    height=&quot;600&quot;
    allowtransparency
&gt;&lt;/iframe&gt;
</code></pre>
<p>You are all set. Just restart your application so the new environment variables are taken in consideration. Voilà, your application now has an integrated Metabase dashboard.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="metabasebanner 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/metabasebanner-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>Today, I am  proposing a very simple tutorial. I needed to integrate a Metabase dashboard in one of my applications and I realized there is no article which explains how to do that. So, ta-da!</p>
<span id="more-2825"></span>

<h2 id="requirements">Requirements</h2>
<p>To follow this tutorial, you will need</p>
<ul>
<li>a Metabase dashboard (read <a href="https://www.clever.cloud/blog/engineering/2019/02/20/how-to-install-metabase/">this article</a> from my fellow Laurent Dogin to have yours set up in a few minutes)</li>
<li>a Ruby on Rails application (read <a href="https://www.clever.cloud/blog/engineering/2019/05/07/setup-your-ruby-on-rails-online-dev-environment/">this article</a> by me if you need to set up one)</li>
</ul>
<h2 id="enabling-integration-in-metabase">Enabling integration in Metabase</h2>
<p>From your Metabase, click on the top right <strong>gear icon</strong>, then <strong>Admin</strong>. On the left menu select <strong>Embedding in other Applications</strong>. Toggle the button to have it saying <strong>Enabled</strong>. You will now get an Embedding API key. Save it for later.</p>
<figure style="position:relative;width:100%;height:auto;margin:0 auto">
  <img data-action="zoom"  alt="Enable integrations on Metabase" src="https://cdn.clever-cloud.com/uploads/2021/08/metabase-integration-screenshot.png"/>
</figure>

<p>Leave Metabase admin and select the dashboard you want to integrate. Click the sharing and embedding icon on the top right of your dashboard. Now select <strong>Embed this dashboard in an Application</strong>. Finally, click on the <strong>Publish</strong> button.</p>
<h2 id="integrate-metabase-in-rails">Integrate Metabase in Rails</h2>
<p>In your Gemfile, add <code>gem &#39;jwt&#39;</code> then run <code>$ bundle install</code>. If your application is deployed on Clever Cloud go to your application&#39;s console and under your application&#39;s menu go to the <strong>environment variables</strong> menu. If you deploy locally, use the <a href="https://github.com/laserlemon/figaro">gem figaro</a> and edit your application.yml. Anyway you must add two environment variables</p>
<pre><code class="language-yaml">METABASE_SITE_URL: &lt;your metabase url&gt;
METABASE_SECRET_KEY: &lt;the API key from metabase admin&gt;
</code></pre>
<p>In the controller action where you want to integrate your metabase dashboard, add the following lines:</p>
<pre><code class="language-ruby">payload = {
          :resource =&gt; {:dashboard =&gt; &lt;your dashboard number&gt;},
          :params =&gt; { },
          :exp =&gt; Time.now.to_i + (60 * 10) # 10 minute expiration
    }
token = JWT.encode(payload, ENV[&quot;METABASE_SECRET_KEY&quot;])
@iframe_url = ENV[&quot;METABASE_SITE_URL&quot;] + &quot;/embed/dashboard/&quot; + token + &quot;#bordered=true&amp;titled=true&quot;
</code></pre>
<p>Now in your view, add</p>
<pre><code class="language-html">&lt;iframe
    src=&quot;&lt;%= @iframe_url %&gt;&quot;
    frameborder=&quot;0&quot;
    width=&quot;800&quot;
    height=&quot;600&quot;
    allowtransparency
&gt;&lt;/iframe&gt;
</code></pre>
<p>You are all set. Just restart your application so the new environment variables are taken in consideration. Voilà, your application now has an integrated Metabase dashboard.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Deploy node projects as static &#8211; MDX-Deck demo</title>
		<link>https://www.clever.cloud/blog/engineering/2020/05/05/deploy-node-mxd-deck/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Tue, 05 May 2020 14:27:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[mxd-deck]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[static deployment]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/05/05/deploy-node-mxd-deck/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="nodebanner 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p>As some of you may know, we love to present tech talks at Clever Cloud, and this often comes with visual presentations slides. There are numerous tools to help you do that, but one particularly caught my attention as it is also destined to developers first.<span id="more-2824"></span> <a href="https://github.com/jxnblk/mdx-deck">MDX-deck</a> allows you to write <a href="https://reactjs.org/">React</a> components and content in <a href="https://www.markdownguide.org/">Markdown</a> among other cool stuffs. Check out the official repo to find out more about the capabilities of the project.

Wether you&#39;re doing presentations or not, read carefully, we are about to deploy a static application made out of a React build and use the Clever Cloud hooks to do so. Ready? Let&#39;s go.
<h3 id="requirements">Requirements</h3>
<ul>
 	<li>you need to have <a href="https://www.npmjs.com/get-npm">npm</a> and <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git">git</a> installed on your machine.</li>
 	<li>you need a <a href="https://api.clever-cloud.com/v2/sessions/signup">Clever Cloud account</a> with at least a validated email to benefit the free credits.</li>
</ul>
<h3 id="setting-up-our-mdx-deck">Setting up our MDX-Deck</h3>
Go to your console and type in
<pre><code class="language-bash">$ mkdir presentation //creating a new folder
$ cd presentation
$ git init // creating fresh git folder
$ npm init //creating new project
</code></pre>
Just type enter for eveything you&#39;re prompted of except for <code>description</code> if you would like to provide one, <code>author</code> that you must fill, <code>license</code> that you can edit to the licence you want your project to be under.

Now we will create our presentation file with <code>$ touch deck.mdx</code> and add the package to the project with <code>$ npm i -D mdx-deck</code>.

Open the project in your text editor and start with fine tuning <code>package.json</code> Here we want to remove the line
<pre><code class="language-json">&quot;main&quot;: &quot;index.js&quot;,
</code></pre>
and add a start and a build command using the mxd-deck CLI with the file we just created to our scripts
<pre><code class="language-json">&quot;scripts&quot;: {
    &quot;start&quot;: &quot;mdx-deck deck.mdx&quot;,
    &quot;build&quot;: &quot;mdx-deck build deck.mdx&quot;,
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;
},
</code></pre>
We will only use <code>start</code> to test locally and use <code>build</code> to deploy. We are done with <code>package.json</code>, we can now move to <code>deck.mdx</code>. Add this in the file:
<pre><code class="language-markdown"># Congratulations!

---

## You&#39;re up and live on Clever Cloud!

---
</code></pre>
You can note that we have just created two slides, each one ending with <code>---</code> and that we are using the Markdown syntax. Let&#39;s see how it renders with <code>npm start</code>. Your browser will open at <code>http://localhost:8000</code> displaying our first slide. Use side arrows to navigate between pages.
<h2 id="deploy-to-clever-cloud-as-static-with-hooks">Deploy to clever cloud as static with hooks</h2>
Now we will create a static application in the <a href="https://console.clever-cloud.com/">Clever Cloud console</a>. Under the organization of our choice, we will click the <strong>Create</strong> button and select <strong>application</strong>, then <strong>Static</strong>. Follow the instructions, and just select <strong>git</strong> when you have the choice between it and FTP. A git remote will be provided to you. Add it to your local repository with the provided command and get back to the Clever Cloud console. Select <strong>Environment variables</strong> in the left menu of your application and add <code>CC_PRE_RUN_HOOK</code> with value <code>npm run build</code> and <code>CC_WEBROOT</code> with value <code>/public</code>. Do not forget to add each new variable and to update changes when you are done editing.

Now we can push our sources to the clever git remote we set previously by adding and committing them, then pushing with <code>$ git push clever master</code>. It is also possible to du it using the Clever Cloud CLI with <code>clever deploy</code>. Documentation <a href="https://www.clever.cloud/developers/clever-tools/getting_started/">here</a>

In the Clever Cloud console, the deployment logs will appear and after a little you will be able to navigate to your application by going to the <strong>overview</strong> page of your application and clicking the link icon on the top right. Use right arrow to navigate to slide two. But what did just happen?
<h2 id="explanation">Explanation</h2>
The <code>CC_PRE_RUN_HOOK</code> is a command run only if specified. This hook is run before the dependencies are fetched and has the specificity to make your deployment fail if it no successful. This is helpful as we do not want to try running a failed build result and have confusing errors harder to debug.
Here, we gave it the value of <code>npm run-script build</code>, this basically tells npm to run our build command specified in <code>package.json</code>. Build command which runs mdx-deck build cli. That leaves us with a new <code>/public</code> folder containing our website static web pages. The other environment variable we used is <code>CC_WEBROOT</code>. This variable tells the server to set the DocumentRoot to the  <code>/public</code> folder wich contains your web pages. This is where a visitor will end up when visiting your website.

You can, of course adapt, it to any other npm project static build.]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="nodebanner 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/nodebanner-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p>As some of you may know, we love to present tech talks at Clever Cloud, and this often comes with visual presentations slides. There are numerous tools to help you do that, but one particularly caught my attention as it is also destined to developers first.<span id="more-2824"></span> <a href="https://github.com/jxnblk/mdx-deck">MDX-deck</a> allows you to write <a href="https://reactjs.org/">React</a> components and content in <a href="https://www.markdownguide.org/">Markdown</a> among other cool stuffs. Check out the official repo to find out more about the capabilities of the project.

Wether you&#39;re doing presentations or not, read carefully, we are about to deploy a static application made out of a React build and use the Clever Cloud hooks to do so. Ready? Let&#39;s go.
<h3 id="requirements">Requirements</h3>
<ul>
 	<li>you need to have <a href="https://www.npmjs.com/get-npm">npm</a> and <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git">git</a> installed on your machine.</li>
 	<li>you need a <a href="https://api.clever-cloud.com/v2/sessions/signup">Clever Cloud account</a> with at least a validated email to benefit the free credits.</li>
</ul>
<h3 id="setting-up-our-mdx-deck">Setting up our MDX-Deck</h3>
Go to your console and type in
<pre><code class="language-bash">$ mkdir presentation //creating a new folder
$ cd presentation
$ git init // creating fresh git folder
$ npm init //creating new project
</code></pre>
Just type enter for eveything you&#39;re prompted of except for <code>description</code> if you would like to provide one, <code>author</code> that you must fill, <code>license</code> that you can edit to the licence you want your project to be under.

Now we will create our presentation file with <code>$ touch deck.mdx</code> and add the package to the project with <code>$ npm i -D mdx-deck</code>.

Open the project in your text editor and start with fine tuning <code>package.json</code> Here we want to remove the line
<pre><code class="language-json">&quot;main&quot;: &quot;index.js&quot;,
</code></pre>
and add a start and a build command using the mxd-deck CLI with the file we just created to our scripts
<pre><code class="language-json">&quot;scripts&quot;: {
    &quot;start&quot;: &quot;mdx-deck deck.mdx&quot;,
    &quot;build&quot;: &quot;mdx-deck build deck.mdx&quot;,
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;
},
</code></pre>
We will only use <code>start</code> to test locally and use <code>build</code> to deploy. We are done with <code>package.json</code>, we can now move to <code>deck.mdx</code>. Add this in the file:
<pre><code class="language-markdown"># Congratulations!

---

## You&#39;re up and live on Clever Cloud!

---
</code></pre>
You can note that we have just created two slides, each one ending with <code>---</code> and that we are using the Markdown syntax. Let&#39;s see how it renders with <code>npm start</code>. Your browser will open at <code>http://localhost:8000</code> displaying our first slide. Use side arrows to navigate between pages.
<h2 id="deploy-to-clever-cloud-as-static-with-hooks">Deploy to clever cloud as static with hooks</h2>
Now we will create a static application in the <a href="https://console.clever-cloud.com/">Clever Cloud console</a>. Under the organization of our choice, we will click the <strong>Create</strong> button and select <strong>application</strong>, then <strong>Static</strong>. Follow the instructions, and just select <strong>git</strong> when you have the choice between it and FTP. A git remote will be provided to you. Add it to your local repository with the provided command and get back to the Clever Cloud console. Select <strong>Environment variables</strong> in the left menu of your application and add <code>CC_PRE_RUN_HOOK</code> with value <code>npm run build</code> and <code>CC_WEBROOT</code> with value <code>/public</code>. Do not forget to add each new variable and to update changes when you are done editing.

Now we can push our sources to the clever git remote we set previously by adding and committing them, then pushing with <code>$ git push clever master</code>. It is also possible to du it using the Clever Cloud CLI with <code>clever deploy</code>. Documentation <a href="https://www.clever.cloud/developers/clever-tools/getting_started/">here</a>

In the Clever Cloud console, the deployment logs will appear and after a little you will be able to navigate to your application by going to the <strong>overview</strong> page of your application and clicking the link icon on the top right. Use right arrow to navigate to slide two. But what did just happen?
<h2 id="explanation">Explanation</h2>
The <code>CC_PRE_RUN_HOOK</code> is a command run only if specified. This hook is run before the dependencies are fetched and has the specificity to make your deployment fail if it no successful. This is helpful as we do not want to try running a failed build result and have confusing errors harder to debug.
Here, we gave it the value of <code>npm run-script build</code>, this basically tells npm to run our build command specified in <code>package.json</code>. Build command which runs mdx-deck build cli. That leaves us with a new <code>/public</code> folder containing our website static web pages. The other environment variable we used is <code>CC_WEBROOT</code>. This variable tells the server to set the DocumentRoot to the  <code>/public</code> folder wich contains your web pages. This is where a visitor will end up when visiting your website.

You can, of course adapt, it to any other npm project static build.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Elastic Basics: Indexation</title>
		<link>https://www.clever.cloud/blog/features/2020/04/02/indexing-elasticsearch-clever-cloud/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Thu, 02 Apr 2020 17:10:00 +0000</pubDate>
				<category><![CDATA[Features]]></category>
		<category><![CDATA[elastic]]></category>
		<category><![CDATA[elasticsearch]]></category>
		<category><![CDATA[indexation]]></category>
		<category><![CDATA[node]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/04/02/indexing-elasticsearch-clever-cloud/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="elastic indexation clever cloud 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>In my <a href="https://www.clever.cloud/blog/features/2020/03/30/elastic-canvas-clever-cloud/">last article</a> I created a simple Canvas workpad in my Kibana. To do so I already had meetup data indexed in my Elastic instance. Today I am going to tell you how I did gather data and added it to Elasticsearch.</p>
<span id="more-2972"></span>

<h2 id="selecting-meetups-i-want-to-track">Selecting meetups I want to track</h2>
<p>The first thing to do is to select a list of meetup groups you want to keep track of. There are many ways to do that using the <a href="https://www.meetup.com/meetup_api/">Meetup API</a>. For instance, you can search to similar groups using the <a href="https://www.meetup.com/fr-FR/meetup_api/docs/:urlname/similar_groups/?uri=%2Fmeetup_api%2Fdocs%2F%3Aurlname%2Fsimilar_groups%2F">similar_groups endpoint</a>. I let you read the API documentation to find a way to select the events you will track. You just need to format the response to extract the cities and the names of the Meetups groups in a JSON file formatted as follows:</p>
<pre><code class="language-json">{
  &quot;City name 1&quot;: [
    &quot;meetup group name 1&quot;,
    &quot;meetup group name 2&quot;,
    ...
  ],
  &quot;City name 2&quot;: [
    &quot;meetup group name 1&quot;,
    ...
  ]
}
</code></pre>
<h2 id="getting-data-about-meetup-events">Getting data about meetup events</h2>
<p>Once you have this, you can use the <a href="https://github.com/CleverCloud/meetups-elastic-import">node.js application we created</a>. Of course it has the Elasticsearch dependency in package.json. You are strongly invited to check out the source code at this point. You can see in the index.js many parts of interest:</p>
<ul>
<li>The creation of an express server listening on port 8080. We need it, so Clever Cloud will know our app is up running.</li>
</ul>
<pre><code class="language-javascript">app.get(&#39;/&#39;, (req, res) =&gt; {
    res.send(&#39;Hello !&#39;);
});
app.listen(8080, () =&gt; console.log(&#39;Listening on port 8080!&#39;)); 
</code></pre>
<ul>
<li>The meetup API call:</li>
</ul>
<pre><code class="language-javascript">axios.get(`https://api.meetup.com/${meetupName}/events/?status=past,upcoming\&amp;fields=comment_count`)
</code></pre>
<ul>
<li>the creation of Elasticsearch indexes:</li>
</ul>
<pre><code class="language-javascript">await client.indices.create({
  index: &quot;meetup&quot;,
  body : {
    &quot;mappings&quot;: {
      &quot;properties&quot;: {
        &quot;time&quot;:  {&quot;type&quot;: &quot;date&quot;, &quot;format&quot;: &quot;epoch_millis&quot;},
        &quot;group.name&quot;: {&quot;type&quot;: &quot;keyword&quot;},
        &quot;yes_rsvp_count&quot; : {&quot;type&quot;: &quot;integer&quot;},
        &quot;grouploc&quot;: {&quot;type&quot;: &quot;geo_point&quot;},
        &quot;venueloc&quot;:{&quot;type&quot;: &quot;geo_point&quot;}
      }
    }
  }
});
</code></pre>
<ul>
<li>The creation of another server where our meetup API calls happen, listening on port 8081. We can also notice that we&#39;ve restricted our server to allow only localhost connections.</li>
</ul>
<pre><code class="language-javascript">localapp.listen(8081, &#39;localhost&#39;, function() {
  console.log(&quot;... port %d in %s mode&quot;, 8081, localapp.settings.env);
</code></pre>
<p>Now in <code>./clevercloud/cron.json</code> you can notice a cron task, wich will trigger a curl on <code>http://localhost:8081/</code> every night at 1 AM:</p>
<pre><code class="language-json">&quot;0 1 * * * /usr/host/bin/curl http://localhost:8081/&quot;
</code></pre>
<p>It is this cron that will call our second server to trigger the meetup API calls.</p>
<p>True fact: to use it in its current version, you must keep your application running all the time for one hour of usage maximum. A way to improve the application regarding this issue would be to implement authentication to our application, so we still are the only one having access.</p>
<p>Then remove the cron from this project to have it running in your main application instead. Your main application will be the one consuming this indexed data. Taking advantage on the fact that every virtual machine running on Clever Cloud already has the Clever Tools CLI installed, we could improve our cron to start the application for an hour then stop it when it has finished its indexation job.</p>
<p>So you will end up with two machines, one with your main application, and the second one running for one hour each night.</p>
<p>We must also know that Clever Cloud does not monitor what&#39;s going on on port 8081. You could add a logging system or use Elastic APM to monitor your application during its execution time.</p>
<p>This is an approach among many others, do not hesitate to talk with us about your own implementation.</p>
<p>Okay, let&#39;s go back to our main goal, and to do so, you can use our sample data meetup list or use your own by replacing the json in the <code>meetups.json</code>file.</p>
<h2 id="try-it-out">Try it out</h2>
<p>You can <code>$ git clone</code> the repo in your console, and go into your Clever Cloud console.</p>
<p>Under the organization of your choice, select <strong>New</strong>, <strong>Application</strong>, <strong>Node</strong>. When prompted if you need add-ons, select <strong>Elastic Stack</strong>, select the plan you need and <strong>enable Kibana</strong> as an option.</p>
<p>In the environment variables menu of your application, add <code>NODE_ENV=production</code> and add the provided <code>clever remote</code> to your local git folder. Then push using <code>git push -u clever master</code>.</p>
<p>Your deployment will start and thanks to the <code>ES_ADDON_URI</code> we provided in our index.js file, we have nothing else to configure, our application will start sending data to elastic.</p>
<h2 id="visualize-your-data-and-go-further">Visualize your data and go further</h2>
<p>Either in your Kibana or Elastic instance menu in the Clever Cloud console, in the information page you will find a <strong>Open Kibana</strong> button. Click it and login using your Clever Cloud credentials.</p>
<p>Into Kibana click on the <strong>Management</strong> (gear) icon in the left side menu. Under the Kibana title, select <strong>Index Patterns</strong>, then <strong>meetup*</strong> to see how the data is indexed.</p>
<figure style="position:relative;width:50%;height:auto;margin:0 auto">
  <img data-action="zoom"  alt="index of meetups in Kibana" src="https://cdn.clever-cloud.com/uploads/2021/08/kibana-meetups.png"/>
</figure>

<p>Of course at this point, you are able to do the exact same as I did in the previous article <a href="https://www.loom.com/share/e36ce43a8d104984bba96cde3c67d714">video</a>.</p>
<p>Here is the ElasticSQL query I used in the Canvas demonstration:</p>
<pre><code class="language-sql">SELECT AVG(&quot;yes_rsvp_count&quot;) AS average, &quot;group.name&quot; FROM &quot;meetup*&quot;
GROUP BY &quot;group.name&quot;
ORDER BY average DESC
LIMIT 5
</code></pre>
<p>Happy indexing!</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="elastic indexation clever cloud 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-indexation-clever-cloud-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>In my <a href="https://www.clever.cloud/blog/features/2020/03/30/elastic-canvas-clever-cloud/">last article</a> I created a simple Canvas workpad in my Kibana. To do so I already had meetup data indexed in my Elastic instance. Today I am going to tell you how I did gather data and added it to Elasticsearch.</p>
<span id="more-2972"></span>

<h2 id="selecting-meetups-i-want-to-track">Selecting meetups I want to track</h2>
<p>The first thing to do is to select a list of meetup groups you want to keep track of. There are many ways to do that using the <a href="https://www.meetup.com/meetup_api/">Meetup API</a>. For instance, you can search to similar groups using the <a href="https://www.meetup.com/fr-FR/meetup_api/docs/:urlname/similar_groups/?uri=%2Fmeetup_api%2Fdocs%2F%3Aurlname%2Fsimilar_groups%2F">similar_groups endpoint</a>. I let you read the API documentation to find a way to select the events you will track. You just need to format the response to extract the cities and the names of the Meetups groups in a JSON file formatted as follows:</p>
<pre><code class="language-json">{
  &quot;City name 1&quot;: [
    &quot;meetup group name 1&quot;,
    &quot;meetup group name 2&quot;,
    ...
  ],
  &quot;City name 2&quot;: [
    &quot;meetup group name 1&quot;,
    ...
  ]
}
</code></pre>
<h2 id="getting-data-about-meetup-events">Getting data about meetup events</h2>
<p>Once you have this, you can use the <a href="https://github.com/CleverCloud/meetups-elastic-import">node.js application we created</a>. Of course it has the Elasticsearch dependency in package.json. You are strongly invited to check out the source code at this point. You can see in the index.js many parts of interest:</p>
<ul>
<li>The creation of an express server listening on port 8080. We need it, so Clever Cloud will know our app is up running.</li>
</ul>
<pre><code class="language-javascript">app.get(&#39;/&#39;, (req, res) =&gt; {
    res.send(&#39;Hello !&#39;);
});
app.listen(8080, () =&gt; console.log(&#39;Listening on port 8080!&#39;)); 
</code></pre>
<ul>
<li>The meetup API call:</li>
</ul>
<pre><code class="language-javascript">axios.get(`https://api.meetup.com/${meetupName}/events/?status=past,upcoming\&amp;fields=comment_count`)
</code></pre>
<ul>
<li>the creation of Elasticsearch indexes:</li>
</ul>
<pre><code class="language-javascript">await client.indices.create({
  index: &quot;meetup&quot;,
  body : {
    &quot;mappings&quot;: {
      &quot;properties&quot;: {
        &quot;time&quot;:  {&quot;type&quot;: &quot;date&quot;, &quot;format&quot;: &quot;epoch_millis&quot;},
        &quot;group.name&quot;: {&quot;type&quot;: &quot;keyword&quot;},
        &quot;yes_rsvp_count&quot; : {&quot;type&quot;: &quot;integer&quot;},
        &quot;grouploc&quot;: {&quot;type&quot;: &quot;geo_point&quot;},
        &quot;venueloc&quot;:{&quot;type&quot;: &quot;geo_point&quot;}
      }
    }
  }
});
</code></pre>
<ul>
<li>The creation of another server where our meetup API calls happen, listening on port 8081. We can also notice that we&#39;ve restricted our server to allow only localhost connections.</li>
</ul>
<pre><code class="language-javascript">localapp.listen(8081, &#39;localhost&#39;, function() {
  console.log(&quot;... port %d in %s mode&quot;, 8081, localapp.settings.env);
</code></pre>
<p>Now in <code>./clevercloud/cron.json</code> you can notice a cron task, wich will trigger a curl on <code>http://localhost:8081/</code> every night at 1 AM:</p>
<pre><code class="language-json">&quot;0 1 * * * /usr/host/bin/curl http://localhost:8081/&quot;
</code></pre>
<p>It is this cron that will call our second server to trigger the meetup API calls.</p>
<p>True fact: to use it in its current version, you must keep your application running all the time for one hour of usage maximum. A way to improve the application regarding this issue would be to implement authentication to our application, so we still are the only one having access.</p>
<p>Then remove the cron from this project to have it running in your main application instead. Your main application will be the one consuming this indexed data. Taking advantage on the fact that every virtual machine running on Clever Cloud already has the Clever Tools CLI installed, we could improve our cron to start the application for an hour then stop it when it has finished its indexation job.</p>
<p>So you will end up with two machines, one with your main application, and the second one running for one hour each night.</p>
<p>We must also know that Clever Cloud does not monitor what&#39;s going on on port 8081. You could add a logging system or use Elastic APM to monitor your application during its execution time.</p>
<p>This is an approach among many others, do not hesitate to talk with us about your own implementation.</p>
<p>Okay, let&#39;s go back to our main goal, and to do so, you can use our sample data meetup list or use your own by replacing the json in the <code>meetups.json</code>file.</p>
<h2 id="try-it-out">Try it out</h2>
<p>You can <code>$ git clone</code> the repo in your console, and go into your Clever Cloud console.</p>
<p>Under the organization of your choice, select <strong>New</strong>, <strong>Application</strong>, <strong>Node</strong>. When prompted if you need add-ons, select <strong>Elastic Stack</strong>, select the plan you need and <strong>enable Kibana</strong> as an option.</p>
<p>In the environment variables menu of your application, add <code>NODE_ENV=production</code> and add the provided <code>clever remote</code> to your local git folder. Then push using <code>git push -u clever master</code>.</p>
<p>Your deployment will start and thanks to the <code>ES_ADDON_URI</code> we provided in our index.js file, we have nothing else to configure, our application will start sending data to elastic.</p>
<h2 id="visualize-your-data-and-go-further">Visualize your data and go further</h2>
<p>Either in your Kibana or Elastic instance menu in the Clever Cloud console, in the information page you will find a <strong>Open Kibana</strong> button. Click it and login using your Clever Cloud credentials.</p>
<p>Into Kibana click on the <strong>Management</strong> (gear) icon in the left side menu. Under the Kibana title, select <strong>Index Patterns</strong>, then <strong>meetup*</strong> to see how the data is indexed.</p>
<figure style="position:relative;width:50%;height:auto;margin:0 auto">
  <img data-action="zoom"  alt="index of meetups in Kibana" src="https://cdn.clever-cloud.com/uploads/2021/08/kibana-meetups.png"/>
</figure>

<p>Of course at this point, you are able to do the exact same as I did in the previous article <a href="https://www.loom.com/share/e36ce43a8d104984bba96cde3c67d714">video</a>.</p>
<p>Here is the ElasticSQL query I used in the Canvas demonstration:</p>
<pre><code class="language-sql">SELECT AVG(&quot;yes_rsvp_count&quot;) AS average, &quot;group.name&quot; FROM &quot;meetup*&quot;
GROUP BY &quot;group.name&quot;
ORDER BY average DESC
LIMIT 5
</code></pre>
<p>Happy indexing!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Elastic feature presentation: Canvas</title>
		<link>https://www.clever.cloud/blog/features/2020/03/30/elastic-canvas-clever-cloud/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Mon, 30 Mar 2020 15:55:00 +0000</pubDate>
				<category><![CDATA[Features]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[elastic]]></category>
		<category><![CDATA[europe]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/03/30/elastic-canvas-clever-cloud/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="elastic canvas 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><h2 id="you-like-kibana-you-will-love-canvas">You like Kibana? You will love Canvas</h2>
<p>Canvas is a feature that comes inside our beloved Kibana dashboard and allows us to visualize and present our data from our Elasticsearch <em>our</em> way.</p>
<span id="more-2971"></span>

<p>Whether you are working with application metrics, security events, infrastructure logs, business-related data or even your side projects, as long as you put the generated info in an Elasticsearch instance, you will be able to display them in an elegant way.</p>
<p>Create workpads with combined data from your Elasticsearch and convert them into beautiful charts, graphs, progress monitors, infographics, reports… The only limit is your imagination (yes, for real)!</p>
<p>You already have a visual identity ? Import your logo, your color schemes, your css to get a consistent interface all over and reuse them everywhere! Share them with your users and customers with ease so your branding is really homogeneous.</p>
<p>Not having a visual identity? There are tons of color palettes and templates you can play around with.</p>
<p>Make your workpads dynamic using time-series data, add your Elastic Maps into your workpads, choose how often it should be updated.</p>
<p>Canvas also lets you customize your workspace with backgrounds, colors, fonts, images and more.</p>
<h2 id="is-it-easy-to-use">Is it easy to use</h2>
<p>What a question! You should know how simple is the Elastic Stack experience!</p>
<p>Canvas arrives out of the box inside Kibana on Clever Cloud, with features like syntax highlighting, mouse-over context-sensitive help, drag and drop publishing, dark mode and more to help you create pixel-perfect visuals with your data.</p>
<p>Use Elasticsearch SQL to design aggregations like you already do in your applications and display them in your workpads.</p>
<p>Canvas comes with its own library of functions to empower your imagination but if it’s not enough, with the <a href="https://www.elastic.co/guide/en/elasticsearch/plugins/7.6/intro.html">Elastic plugin framework</a>, you can also add your own plugins or community ones no matter how experienced in development you are.</p>
<p>And thanks to Clever Cloud, keeping everything in operating condition is pretty simple, as we manage this for you. While as usual providing you a Europe-based infrastructure, GDPR compliant and protected from Cloud Act.</p>
<h2 id="reuse-your-workpads-everywhere">Reuse your workpads everywhere</h2>
<p>You might wonder: what can I do with my awesome creations? Well, actually almost everything!</p>
<p>You can, of course, use them in your Kibana, but here are some examples of usage you can have outside of your dashboards:</p>
<ul>
<li>export your workpads as JSON</li>
<li>generate one shot PDF</li>
<li>automate PDF reporting with a POST endpoint</li>
<li>display your workpads on websites (and customize them there to match the design of the page)</li>
<li>get live reporting on screens in your office, retail points or any place</li>
<li>add real data to your weekly, monthly … emails</li>
</ul>
<p>Once again, the only limit is your imagination! </p>
<div style="position: relative; padding-bottom: 50.919377652050926%; height: 0;">
  <iframe src="https://www.loom.com/embed/e36ce43a8d104984bba96cde3c67d714" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe>
</div>
<br>

<p>Do not hesitate to try out Canvas, it is really easy to use and available in one click and stay tuned, next time I’ll show you how I indexed meetups data into Elastic.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="elastic canvas 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/elastic-canvas-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><h2 id="you-like-kibana-you-will-love-canvas">You like Kibana? You will love Canvas</h2>
<p>Canvas is a feature that comes inside our beloved Kibana dashboard and allows us to visualize and present our data from our Elasticsearch <em>our</em> way.</p>
<span id="more-2971"></span>

<p>Whether you are working with application metrics, security events, infrastructure logs, business-related data or even your side projects, as long as you put the generated info in an Elasticsearch instance, you will be able to display them in an elegant way.</p>
<p>Create workpads with combined data from your Elasticsearch and convert them into beautiful charts, graphs, progress monitors, infographics, reports… The only limit is your imagination (yes, for real)!</p>
<p>You already have a visual identity ? Import your logo, your color schemes, your css to get a consistent interface all over and reuse them everywhere! Share them with your users and customers with ease so your branding is really homogeneous.</p>
<p>Not having a visual identity? There are tons of color palettes and templates you can play around with.</p>
<p>Make your workpads dynamic using time-series data, add your Elastic Maps into your workpads, choose how often it should be updated.</p>
<p>Canvas also lets you customize your workspace with backgrounds, colors, fonts, images and more.</p>
<h2 id="is-it-easy-to-use">Is it easy to use</h2>
<p>What a question! You should know how simple is the Elastic Stack experience!</p>
<p>Canvas arrives out of the box inside Kibana on Clever Cloud, with features like syntax highlighting, mouse-over context-sensitive help, drag and drop publishing, dark mode and more to help you create pixel-perfect visuals with your data.</p>
<p>Use Elasticsearch SQL to design aggregations like you already do in your applications and display them in your workpads.</p>
<p>Canvas comes with its own library of functions to empower your imagination but if it’s not enough, with the <a href="https://www.elastic.co/guide/en/elasticsearch/plugins/7.6/intro.html">Elastic plugin framework</a>, you can also add your own plugins or community ones no matter how experienced in development you are.</p>
<p>And thanks to Clever Cloud, keeping everything in operating condition is pretty simple, as we manage this for you. While as usual providing you a Europe-based infrastructure, GDPR compliant and protected from Cloud Act.</p>
<h2 id="reuse-your-workpads-everywhere">Reuse your workpads everywhere</h2>
<p>You might wonder: what can I do with my awesome creations? Well, actually almost everything!</p>
<p>You can, of course, use them in your Kibana, but here are some examples of usage you can have outside of your dashboards:</p>
<ul>
<li>export your workpads as JSON</li>
<li>generate one shot PDF</li>
<li>automate PDF reporting with a POST endpoint</li>
<li>display your workpads on websites (and customize them there to match the design of the page)</li>
<li>get live reporting on screens in your office, retail points or any place</li>
<li>add real data to your weekly, monthly … emails</li>
</ul>
<p>Once again, the only limit is your imagination! </p>
<div style="position: relative; padding-bottom: 50.919377652050926%; height: 0;">
  <iframe src="https://www.loom.com/embed/e36ce43a8d104984bba96cde3c67d714" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe>
</div>
<br>

<p>Do not hesitate to try out Canvas, it is really easy to use and available in one click and stay tuned, next time I’ll show you how I indexed meetups data into Elastic.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Get Elastic APM ready in 5&#8242; on Clever Cloud</title>
		<link>https://www.clever.cloud/blog/features/2020/03/12/deploy-elastic-apm-in-five-minutes/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Thu, 12 Mar 2020 11:15:00 +0000</pubDate>
				<category><![CDATA[Features]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/03/12/deploy-elastic-apm-in-five-minutes/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="apm elastic clever cloud 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p>APM means Application Performance Monitoring. When we say APM in the IT context, we refer to solutions that monitor the platform hosting the application and the app itself.

APM solutions extract information and data about processes, memory usage, disk reading or writing operations/seconds, and other information about the hosting platform.<span id="more-2970"></span> On the application side, they monitor in and out requests, errors, issues, and even code execution to highlight memory and time consuming processes.

These tools can be very important when you are on a cloud based service that auto scales, because some of these issues may be hidden by the auto allocation of more resources to an application. They also give the opportunity to check if the cloud provider's SLA is honored.
<h2 id="apm-by-elastic">APM by Elastic</h2>
Available since version 6.2 (released in 2018), <a href="https://www.elastic.co/products/apm">Elastic APM</a> has proven its efficiency on monitoring and improving applications. Elastic APM monitors in real-time memory allocations, bandwidth usage, data rates, response time, database queries, CPU resources on the client side, calls to cache, unhandled errors and exceptions with their stack trace, aggregates logs in a pretty format and much more thanks to client and server side APM agents.

Distributed tracing feature allows you to see how a request flows into your micro-services architecture and to identify what exactly needs to be improved.

As all the collected data are stored and indexed in Elasticsearch, it's very easy to query them and point out bottlenecks.

Additionally, data is automatically available to consultation in a <a href="https://www.elastic.co/fr/products/kibana">Kibana</a> dashboard. This dashboard comes with a special UI from Elastic where you can conveniently explore your data via generated charts, see metrics about CPU and system memory usage, get the best out of their default filtering by request type, request results, errors with the already identified culprit. And of course you can investigate by search, all of this working out of the box.

And as if it was not enough to really improve our "coding, debugging and releasing" workflows, Elastic APM can send email alerts or Slack notifications when issues arise.

From a practical point of view, APM needs an instance of Elasticsearch, an APM server, Kibana and an agent on the application side. On Clever Cloud, all you need to do is to configure your application to use the agent. Let's see how to do that.

<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte9da1a8d579819a3/5dcb10f1257ee801fd16d1ab/screenshot-kibana-apm-os-dashboard.jpg" alt="APM dashboard in kibana" />
<h2 id="elastic-apm-on-clever-cloud">Elastic APM on Clever Cloud</h2>
If you have read other blog posts of mine, you may know that I'm a Ruby on Rails lover, so no surprise if I chose this Framework to demonstrate how easy it is to get started with the Elastic APM on Clever Cloud. However, APM Agents are available in many languages, so you can follow this tutorial and replace the Ruby on Rails application by one of yours hosted on Clever Cloud that is written in one of the following languages: Go, Java, JavaScript (backend or frontend) or Python.
<h3 id="creating-the-rails-application">Creating the Rails application</h3>
Well, I'm not really a person that likes to do the same thing twice so as I already wrote an article on how to deploy Ruby on Rails applications on Clever Cloud, I will start this tutorial by considering you already have an application running like at the end of my previous article. If you don't, do not hesitate to take a break to follow <a href="https://www.clever.cloud/blog/engineering/2019/05/07/setup-your-ruby-on-rails-online-dev-environment/">the tutorial</a>, it takes five minutes to be all set.
<h3 id="creating-the-es-stack-on-clever-cloud">Creating the ES stack on Clever Cloud</h3>
Well, it's pretty easy:
<ul>
 	<li>Go to your Clever Cloud console, under the organization where your application lives, select <strong>Create</strong> then <strong>an add-on</strong>. Scroll down until you find and select <strong>Elastic Stack</strong>.</li>
 	<li>On the next screen select the plan you need, there is no minimal size to benefit from these features.</li>
 	<li>On the next screen enable APM and Kibana</li>
 	<li>You will now be prompted to name your add-on, and you will be able to select the deployment region. Fine tune as you need and press <strong>next</strong>.</li>
 	<li>Go to the <strong>Service dependencies</strong> section of your application, then select the APM server in the <strong>Link applications</strong> drop down menu.</li>
</ul>
The Elastic Stack add-on will be automatically created: Elasticsearch, an APM server and a Kibana instance will start. You will see them appear shortly under your organization; there's nothing more you need to do to start using them.

If you navigate to your application's <strong>Environment variables</strong> menu, you will see that you can now use environment variables provided by the add-on we just created. And fortunately this is almost everything we need to finish this configuration.

<strong>⚠️ Warning:</strong> Make sure that you linked the <ins>APM server</ins>, and not the Elastic add-on. Otherwise, you won't have the correct ENV VAR for the next steps.
<h3 id="configure-your-application-for-apm">Configure your Application for APM</h3>
<h4 id="ruby-on-rails">Ruby on Rails</h4>
Go in your terminal, under your application repository.
<ul>
 	<li>with your favorite text editor, edit the <code>Gemfile</code> to add <code>gem 'elastic-apm'</code>.</li>
 	<li>Create a file named <code>config/elastic_apm.yml</code> that you will fill with this:</li>
</ul>
<pre><code class="language-yaml">server_url: &lt;%= ENV["ELASTIC_APM_SERVER_URLS"] %&gt; 
secret_token: &lt;%= ENV["ELASTIC_APM_SECRET_TOKEN"] %&gt;
</code></pre>
You may here notice the usage of environment variables to protect APM server's secrets. You can use these environment variables thanks to linking your application to your APM server on Clever Cloud.
<h4 id="other-languages">Other languages</h4>
You can find <a href="https://www.elastic.co/guide/en/apm/agent/index.html">here</a> the list of all the APM agents by language. You can just follow the simple steps and refer to the environment variables mentioned in the Ruby on Rails section to replace host url and secret token values. You may also need to use additional environment variables, read <a href="https://www.clever.cloud/developers/doc/administrate/">this</a> to add them to your Clever Cloud application.
<h3 id="deploying-the-apm-agent">Deploying the APM agent</h3>
Okay, that was it. Now, you can add, commit and push these changes to Clever Cloud either via the CLI <code>clever deploy</code> or by pushing on the Clever Cloud git remote (usually named <code>clever</code>) of your application using <code>git push clever master</code>. Your application will restart within seconds and instantly connect to the APM server thanks to the environment variables we provided.
<h3 id="enjoying-your-apm--kibana">Enjoying your APM / Kibana</h3>
Now that our application is restarted, we can go to our Kibana application in Clever Cloud and click the link icon at the top right of the application menus. This will open a new tab with a Clever Cloud login form. Connect with your Clever Cloud credentials. This will open your Kibana after a brief apparition of a Keycloak page.

As Keycloak is not the topic here, all I'll say is that authentication to Kibana is delegated to Clever Cloud using this solution. If you want to know more about it, <a href="https://www.clever.cloud/developers/addons/elastic/#kibana">read this</a>.

In Kibana, find the APM section in the menu on the left (tip: you can unroll the menu with a button at the bottom of the menu). Click it and <em>Wow!</em> you already can visualize your first application performance metrics in the beautiful Elastic UI for Kibana.

Here's a step by step video:
<div style="position: relative; padding-bottom: 50.79962370649106%; height: 0;"><iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" src="https://www.loom.com/embed/af70aab3a26a41ac88cdb8094fd64862" frameborder="0" allowfullscreen="allowfullscreen"></iframe></div>
<h2 id="going-further">Going further</h2>
What we've done so far is pretty great as we can now monitor our applications performances in real time and we needed to setup almost nothing. This is <em>way</em> better than having nothing, but if you're familiar with APM tools you may want to customize and/or add more data to your reportings.

You can read the configuration section of each agent to get the best out of the configuration file we created. You will be able to extend the APM server side agent's configuration like adding your own tags and key filters, decide what exactly you want to capture for each request to your server, fine tune the way the data is sent to the APM server including size and time of the requests and much more. You can learn more about the data model of the events captured by APM <a href="https://www.elastic.co/guide/en/apm/get-started/current/apm-data-model.html">here</a>. You are going to learn here how to enrich your events with metadata to really customize your data. If your application is client side, you can enable the RUM (Real User Monitoring) by starting <a href="https://www.elastic.co/guide/en/apm/get-started/current/rum.html">here</a>.

Happy monitoring!]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="apm elastic clever cloud 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/apm-elastic-clever-cloud-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p>APM means Application Performance Monitoring. When we say APM in the IT context, we refer to solutions that monitor the platform hosting the application and the app itself.

APM solutions extract information and data about processes, memory usage, disk reading or writing operations/seconds, and other information about the hosting platform.<span id="more-2970"></span> On the application side, they monitor in and out requests, errors, issues, and even code execution to highlight memory and time consuming processes.

These tools can be very important when you are on a cloud based service that auto scales, because some of these issues may be hidden by the auto allocation of more resources to an application. They also give the opportunity to check if the cloud provider's SLA is honored.
<h2 id="apm-by-elastic">APM by Elastic</h2>
Available since version 6.2 (released in 2018), <a href="https://www.elastic.co/products/apm">Elastic APM</a> has proven its efficiency on monitoring and improving applications. Elastic APM monitors in real-time memory allocations, bandwidth usage, data rates, response time, database queries, CPU resources on the client side, calls to cache, unhandled errors and exceptions with their stack trace, aggregates logs in a pretty format and much more thanks to client and server side APM agents.

Distributed tracing feature allows you to see how a request flows into your micro-services architecture and to identify what exactly needs to be improved.

As all the collected data are stored and indexed in Elasticsearch, it's very easy to query them and point out bottlenecks.

Additionally, data is automatically available to consultation in a <a href="https://www.elastic.co/fr/products/kibana">Kibana</a> dashboard. This dashboard comes with a special UI from Elastic where you can conveniently explore your data via generated charts, see metrics about CPU and system memory usage, get the best out of their default filtering by request type, request results, errors with the already identified culprit. And of course you can investigate by search, all of this working out of the box.

And as if it was not enough to really improve our "coding, debugging and releasing" workflows, Elastic APM can send email alerts or Slack notifications when issues arise.

From a practical point of view, APM needs an instance of Elasticsearch, an APM server, Kibana and an agent on the application side. On Clever Cloud, all you need to do is to configure your application to use the agent. Let's see how to do that.

<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte9da1a8d579819a3/5dcb10f1257ee801fd16d1ab/screenshot-kibana-apm-os-dashboard.jpg" alt="APM dashboard in kibana" />
<h2 id="elastic-apm-on-clever-cloud">Elastic APM on Clever Cloud</h2>
If you have read other blog posts of mine, you may know that I'm a Ruby on Rails lover, so no surprise if I chose this Framework to demonstrate how easy it is to get started with the Elastic APM on Clever Cloud. However, APM Agents are available in many languages, so you can follow this tutorial and replace the Ruby on Rails application by one of yours hosted on Clever Cloud that is written in one of the following languages: Go, Java, JavaScript (backend or frontend) or Python.
<h3 id="creating-the-rails-application">Creating the Rails application</h3>
Well, I'm not really a person that likes to do the same thing twice so as I already wrote an article on how to deploy Ruby on Rails applications on Clever Cloud, I will start this tutorial by considering you already have an application running like at the end of my previous article. If you don't, do not hesitate to take a break to follow <a href="https://www.clever.cloud/blog/engineering/2019/05/07/setup-your-ruby-on-rails-online-dev-environment/">the tutorial</a>, it takes five minutes to be all set.
<h3 id="creating-the-es-stack-on-clever-cloud">Creating the ES stack on Clever Cloud</h3>
Well, it's pretty easy:
<ul>
 	<li>Go to your Clever Cloud console, under the organization where your application lives, select <strong>Create</strong> then <strong>an add-on</strong>. Scroll down until you find and select <strong>Elastic Stack</strong>.</li>
 	<li>On the next screen select the plan you need, there is no minimal size to benefit from these features.</li>
 	<li>On the next screen enable APM and Kibana</li>
 	<li>You will now be prompted to name your add-on, and you will be able to select the deployment region. Fine tune as you need and press <strong>next</strong>.</li>
 	<li>Go to the <strong>Service dependencies</strong> section of your application, then select the APM server in the <strong>Link applications</strong> drop down menu.</li>
</ul>
The Elastic Stack add-on will be automatically created: Elasticsearch, an APM server and a Kibana instance will start. You will see them appear shortly under your organization; there's nothing more you need to do to start using them.

If you navigate to your application's <strong>Environment variables</strong> menu, you will see that you can now use environment variables provided by the add-on we just created. And fortunately this is almost everything we need to finish this configuration.

<strong>⚠️ Warning:</strong> Make sure that you linked the <ins>APM server</ins>, and not the Elastic add-on. Otherwise, you won't have the correct ENV VAR for the next steps.
<h3 id="configure-your-application-for-apm">Configure your Application for APM</h3>
<h4 id="ruby-on-rails">Ruby on Rails</h4>
Go in your terminal, under your application repository.
<ul>
 	<li>with your favorite text editor, edit the <code>Gemfile</code> to add <code>gem 'elastic-apm'</code>.</li>
 	<li>Create a file named <code>config/elastic_apm.yml</code> that you will fill with this:</li>
</ul>
<pre><code class="language-yaml">server_url: &lt;%= ENV["ELASTIC_APM_SERVER_URLS"] %&gt; 
secret_token: &lt;%= ENV["ELASTIC_APM_SECRET_TOKEN"] %&gt;
</code></pre>
You may here notice the usage of environment variables to protect APM server's secrets. You can use these environment variables thanks to linking your application to your APM server on Clever Cloud.
<h4 id="other-languages">Other languages</h4>
You can find <a href="https://www.elastic.co/guide/en/apm/agent/index.html">here</a> the list of all the APM agents by language. You can just follow the simple steps and refer to the environment variables mentioned in the Ruby on Rails section to replace host url and secret token values. You may also need to use additional environment variables, read <a href="https://www.clever.cloud/developers/doc/administrate/">this</a> to add them to your Clever Cloud application.
<h3 id="deploying-the-apm-agent">Deploying the APM agent</h3>
Okay, that was it. Now, you can add, commit and push these changes to Clever Cloud either via the CLI <code>clever deploy</code> or by pushing on the Clever Cloud git remote (usually named <code>clever</code>) of your application using <code>git push clever master</code>. Your application will restart within seconds and instantly connect to the APM server thanks to the environment variables we provided.
<h3 id="enjoying-your-apm--kibana">Enjoying your APM / Kibana</h3>
Now that our application is restarted, we can go to our Kibana application in Clever Cloud and click the link icon at the top right of the application menus. This will open a new tab with a Clever Cloud login form. Connect with your Clever Cloud credentials. This will open your Kibana after a brief apparition of a Keycloak page.

As Keycloak is not the topic here, all I'll say is that authentication to Kibana is delegated to Clever Cloud using this solution. If you want to know more about it, <a href="https://www.clever.cloud/developers/addons/elastic/#kibana">read this</a>.

In Kibana, find the APM section in the menu on the left (tip: you can unroll the menu with a button at the bottom of the menu). Click it and <em>Wow!</em> you already can visualize your first application performance metrics in the beautiful Elastic UI for Kibana.

Here's a step by step video:
<div style="position: relative; padding-bottom: 50.79962370649106%; height: 0;"><iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" src="https://www.loom.com/embed/af70aab3a26a41ac88cdb8094fd64862" frameborder="0" allowfullscreen="allowfullscreen"></iframe></div>
<h2 id="going-further">Going further</h2>
What we've done so far is pretty great as we can now monitor our applications performances in real time and we needed to setup almost nothing. This is <em>way</em> better than having nothing, but if you're familiar with APM tools you may want to customize and/or add more data to your reportings.

You can read the configuration section of each agent to get the best out of the configuration file we created. You will be able to extend the APM server side agent's configuration like adding your own tags and key filters, decide what exactly you want to capture for each request to your server, fine tune the way the data is sent to the APM server including size and time of the requests and much more. You can learn more about the data model of the events captured by APM <a href="https://www.elastic.co/guide/en/apm/get-started/current/apm-data-model.html">here</a>. You are going to learn here how to enrich your events with metadata to really customize your data. If your application is client side, you can enable the RUM (Real User Monitoring) by starting <a href="https://www.elastic.co/guide/en/apm/get-started/current/rum.html">here</a>.

Happy monitoring!]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Upcoming 2020 conferences</title>
		<link>https://www.clever.cloud/blog/company/2020/03/02/upcoming-conferences-2020/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Mon, 02 Mar 2020 11:00:00 +0000</pubDate>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[conferences]]></category>
		<category><![CDATA[meet]]></category>
		<category><![CDATA[speakers]]></category>
		<category><![CDATA[sponsoring]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/03/02/upcoming-conferences-2020/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="2020 conferences 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>At Clever Cloud, we really love tech conferences. It is a great opportunity for us to share our best stories, show and tell what we do all year long, meet in person a ton of interesting people including our users and offer the best tee-shirts out there, our amazing Sticker Mule <a href="https://www.stickermule.com/eu/uses/laptop-stickers">laptop stickers</a> and the famous 7in1 pens ;)</p>
<span id="more-2771"></span>

<figure>
<center>
<img alt="put an alt please" style="max-width:230px" src="https://cdn.clever-cloud.com/uploads/2021/08/imgs-stickers.com_.jpg"/>
</center>
</figure>

<p>If you would like to meet us this year, here is the list of the conferences we will be at until July 2020.</p>
<h3 id="usa">USA</h3>
<ul>
<li><a href="https://devnexus.com/">Dev Nexus</a>, Atlanta, GA, <em>February 19 to 21</em></li>
<li><a href="https://lonestarelixir.com/">Lonestar Elixir</a>, Austin, TX, <em>February 27 to 28</em></li>
</ul>
<h3 id="france">France</h3>
<ul>
<li><a href="https://www.devoxx.fr/">Devoxx France</a>, Paris, France, <em>April 15 to 17</em> </li>
<li><a href="https://sunny-tech.io/">Sunny Tech</a>, Montpellier, France, <em>July 2 to 3</em></li>
</ul>
<h3 id="poland">Poland</h3>
<ul>
<li><a href="https://www.elixirconf.eu/">Elixir Conf EU</a>, Warsaw, Poland, <em>April 29 to 30</em></li>
</ul>
<h3 id="united-kingdom">United-Kingdom</h3>
<ul>
<li><a href="https://www.devoxx.co.uk/">Devoxx UK</a>, London, UK, <em>May 13 to 15</em></li>
</ul>
<h3 id="germany">Germany</h3>
<ul>
<li><a href="https://phpconference.com/">International PHP Conference</a>, Berlin, Germany, <em>May 25 to 29</em></li>
</ul>
<h3 id="republic-of-ireland">Republic of Ireland</h3>
<ul>
<li><a href="https://ep2020.europython.eu/">Euro Python</a>, Dublin, Republic of Ireland, <em>July 22 to 24</em></li>
</ul>
<p>As we often travel a day before and leave a day after, if you want us to give a talk or meet around the conference, please send an email to <a href="mailto:devrel@clever-cloud.com">deverel (at) clever-cloud.com</a>. Same if you want us to come to a particular conference.</p>
<p>Stay tunned for next upcoming conferences and general news on Twitter <a href="https://twitter.com/clever_cloud">Follow @Clever_Cloud</a></p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="2020 conferences 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/2020-conferences-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>At Clever Cloud, we really love tech conferences. It is a great opportunity for us to share our best stories, show and tell what we do all year long, meet in person a ton of interesting people including our users and offer the best tee-shirts out there, our amazing Sticker Mule <a href="https://www.stickermule.com/eu/uses/laptop-stickers">laptop stickers</a> and the famous 7in1 pens ;)</p>
<span id="more-2771"></span>

<figure>
<center>
<img alt="put an alt please" style="max-width:230px" src="https://cdn.clever-cloud.com/uploads/2021/08/imgs-stickers.com_.jpg"/>
</center>
</figure>

<p>If you would like to meet us this year, here is the list of the conferences we will be at until July 2020.</p>
<h3 id="usa">USA</h3>
<ul>
<li><a href="https://devnexus.com/">Dev Nexus</a>, Atlanta, GA, <em>February 19 to 21</em></li>
<li><a href="https://lonestarelixir.com/">Lonestar Elixir</a>, Austin, TX, <em>February 27 to 28</em></li>
</ul>
<h3 id="france">France</h3>
<ul>
<li><a href="https://www.devoxx.fr/">Devoxx France</a>, Paris, France, <em>April 15 to 17</em> </li>
<li><a href="https://sunny-tech.io/">Sunny Tech</a>, Montpellier, France, <em>July 2 to 3</em></li>
</ul>
<h3 id="poland">Poland</h3>
<ul>
<li><a href="https://www.elixirconf.eu/">Elixir Conf EU</a>, Warsaw, Poland, <em>April 29 to 30</em></li>
</ul>
<h3 id="united-kingdom">United-Kingdom</h3>
<ul>
<li><a href="https://www.devoxx.co.uk/">Devoxx UK</a>, London, UK, <em>May 13 to 15</em></li>
</ul>
<h3 id="germany">Germany</h3>
<ul>
<li><a href="https://phpconference.com/">International PHP Conference</a>, Berlin, Germany, <em>May 25 to 29</em></li>
</ul>
<h3 id="republic-of-ireland">Republic of Ireland</h3>
<ul>
<li><a href="https://ep2020.europython.eu/">Euro Python</a>, Dublin, Republic of Ireland, <em>July 22 to 24</em></li>
</ul>
<p>As we often travel a day before and leave a day after, if you want us to give a talk or meet around the conference, please send an email to <a href="mailto:devrel@clever-cloud.com">deverel (at) clever-cloud.com</a>. Same if you want us to come to a particular conference.</p>
<p>Stay tunned for next upcoming conferences and general news on Twitter <a href="https://twitter.com/clever_cloud">Follow @Clever_Cloud</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Clean up your Rails Controllers with Service Objects</title>
		<link>https://www.clever.cloud/blog/engineering/2019/06/14/clean-controllers-service-object-rails/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Fri, 14 Jun 2019 14:35:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[separation of concerns]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2019/06/14/clean-controllers-service-object-rails/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="banner service objects 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><h2 id="fat-models-and-skinny-controllers-right">Fat Models and skinny Controllers right?</h2>
<p>You know what they say about the MVC design pattern, keep your Controllers light.<br>So at the beginning of your project, you added oil and gears to your Models and it was rolling just fine. Even if I&#39;m not a big fan of the big Model that even makes coffee (sending an email, really?), I can say that you were in perfect harmony with the framework principles.<br>Well, a few iterations later, this idyllic codebase seems very far away and your Controllers and Models are way more &#39;200 line&#39;ish than they used to be.</p>
<span id="more-2821"></span>

<p>Service Objects is a good solution to extract some logic out of them by transferring code into simple services that handles only one thing. This way, you end up with maintainable, super understandable and separated critical code.<br>On this article I&#39;m focusing on Controllers, but the principles are the same for Models. Now, some may ask, why not using Controller Helpers instead?</p>
<p>My answer to that would be: don&#39;t choose, use both!</p>
<h2 id="service-object-and-controller-helper">Service object and Controller helper</h2>
<p>Controller Helpers do hold code shared between Controllers and are also a good way to keep slim Controllers. They are great to respect the DRY (Don&#39;t Repeat Yourself) principles. If you target the same workflows in many Controllers, you must consider putting this logic into a helper. The code you put here is a simple succession of actions you do and conditions you are evaluating. They are useful only if used by at least two Controllers, otherwise, you should think of some code refactoring.<br>Anyway, we often hear that backend logic should not belong to the Controller and just moving everything into a helper won&#39;t solve the problem.</p>
<p>For every operation tied to your business logic (calling an API, calculation) performed in this duplicated code or present in any Controller, you should definitely consider creating a service object for each chunk of logic.</p>
<p>Okay, now you know when to use a service object, but what is it exactly?</p>
<figure>
  <img style="width:50%;margin-left:25%" alt="A League of Legends poro" src="https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/048fa9cc-2f1d-4920-b29d-c80d7aafb488/d63wx6c-8af07a43-f112-489d-9087-e9c10077b7c8.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzA0OGZhOWNjLTJmMWQtNDkyMC1iMjlkLWM4MGQ3YWFmYjQ4OFwvZDYzd3g2Yy04YWYwN2E0My1mMTEyLTQ4OWQtOTA4Ny1lOWMxMDA3N2I3YzgucG5nIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.5MEQgeD-7_FV8NIh-rv8j8gw6FYgyQBuG_eOVUHq0Rc"/>
  <figcaption>A fluffy poro ! - Art by justduet on DeviantArt</figcaption>
</figure>

<p>A service object is a PORO. No, not that cute fluffy League of Legends NPC, but a Plain Old Ruby Object.<br>You just create a class not related to ActiveRecord (the RubyOnRails ORM) with it&#39;s own methods, put your code there, and WOW, you now have a PORO!<br>We will see how we construct it later, first we need to know where to put it in our project.</p>
<h2 id="break-it-to-rebuild-it">Break it to rebuild it</h2>
<p>First, let&#39;s take this Controller. One thing we can notice is an API call in this <code>get_weather</code> method and this should not be Controller business.</p>
<pre><code class="language-ruby">class HomeController &lt; ApplicationController
    require &#39;curb&#39;
    def index
    end

    def get_weather
        http = Curl.get(&quot;#{ENV[&quot;api_base&quot;]}#{ENV[&quot;api_key&quot;]}&quot;)
        if http.status = &quot;200 OK&quot;
            response_body = JSON.parse http.body_str
            @current_weather = response_body[&quot;weather&quot;][0][&quot;description&quot;]
            @current_temperature = &quot;#{(response_body[&quot;main&quot;][&quot;temp&quot;].to_f - 273.15).round(1)} °C&quot;
        else
            @current_weather = &quot;There was an error sorry: #{current_weather[:error]}&quot;
        end
    end
end
</code></pre>
<p>According to the name of the design pattern, we will create a <code>services</code> folder at <code>root_path/app/services/</code>.<br>Okay, looks like it&#39;s about getting weather informations so we will name another folder accordingly.<br>Finally, we can create our service object file. For this, we will be the most explicit and we will use something like <em>x_service.rb</em>.</p>
<p>Being precise on naming and using the <code>_service</code> suffix is here to help other code maintainers to easily understand what is the purpose of the service and where to find it in the project.</p>
<h3 id="skeleton">Skeleton</h3>
<p>This is how we should start every new service object. Here, we can note the import of the library &quot;ostruct&quot;. This allows us to use the OpenStruct object in order to return a rich object containing error messages and a <code>success?</code> method.</p>
<pre><code class="language-ruby">class FolderName::NameOfTheService
    require &quot;ostruct&quot;
    
    def initialize(params={})
        @params = params
    end

    def call
        begin
        rescue =&gt; exception
            OpenStruct.new(success?: false,
                           error: exception.message)
        else
            OpenStruct.new(success?: true, 
                           error: nil)
        end
    end

end
</code></pre>
<h3 id="filling-it-up">Filling it up</h3>
<p>Instead of just copying our Controller&#39;s code into our private method, we will use the wide known begin/rescue pattern to manage errors and will use it at our advantage to raise our own errors.  </p>
<pre><code class="language-ruby">class Weather::GetCurrentWeatherService
  require &quot;ostruct&quot;

    def initialize(params={})
      @params = params
    end

    def call
      @api_base = ENV[&quot;api_base&quot;]
      @api_key = ENV[&quot;api_key&quot;]

      begin
        http = Curl.get(&quot;#{@api_base}#{@api_key}&quot;)
        if http.status == &quot;200 OK&quot;
          response_body = JSON.parse http.body_str
          if response_body[&quot;weather&quot;] &amp;&amp; response_body[&quot;main&quot;]
            weather_string = response_body[&quot;weather&quot;][0][&quot;description&quot;]
            temperature = &quot;#{(response_body[&quot;main&quot;][&quot;temp&quot;].to_f - 273.15).round(1)} °C&quot;
          else
            raise
          end
        else
          raise
        end
      rescue =&gt; exception
          OpenStruct.new(success?: false,
                 error: exception.message)
        else
          OpenStruct.new(success?: true, 
                 weather_string: weather_string, 
                 temperature: temperature, 
                 error: nil)
        end
    end

end
</code></pre>
<h3 id="lets-refactor-this-controller">Let&#39;s refactor this Controller</h3>
<pre><code class="language-ruby">def get_weather
    current_weather = ::Weather::GetCurrentWeatherService.new.call(params: {})
    if current_weather.success?
        @current_weather = current_weather[:weather_string]
        @current_temperature = current_weather[:temperature]
    else
        @current_weather = &quot;There was an error sorry: #{current_weather[:error]}&quot;
    end
end
</code></pre>
<p>We simply call a new instance of our service in our Controller and use it&#39;s <code>success?</code> method to handle regular Controller rendering logic. Note the use of the prepending <code>::</code> it&#39;s for preventing the Controller to look for the service only in its own repository.<br>Here, the params argument is just an empty hash that I do not use but this was to show that, like every PORO, a service can take many parameters.</p>
<h2 id="this-pattern-is-so-great-but-ive-made-a-mess">This pattern is so great, but I&#39;ve made a mess!</h2>
<p>If our weather service was real, we would probably want to handle city search, forecast weather and so on. Maybe we would have extended our service object or created a bunch of others and now it&#39;s an obscure code to maintain and you can feel like you&#39;re drowning. No worries, it&#39;s just time for you to be rescued by NameSpacing!</p>
<p>In fact we already used it by putting our service in a weather folder in the first place. You should definitely classify all your new services by folders and never hesitate to create a sub folder when your folder holds too many service files.<br>If your services can be sliced by fields of usage or are really tied to a Model or Controller, create new folders and move your services under the corresponding ones.</p>
<p>For naming your folders, no master rule, but logic, efficiency, and consistency between the names.<br>Of course, you will need to rename your services. For instance, under a folder named <code>my_folder/my_folder_2</code> your <code>my_service</code> will be renamed <code>MyFolder::MyFolder2::MyService</code> and you will now use the same name in your Controllers to use them.</p>
<h2 id="so-so-or-not">So, SO or not?</h2>
<p>As you may have notice, I was mostly giving advices on how to implement it and never refer to the official documentation.<br>This is because this pattern does not have any convention and everyone can implement it its own way. In order to avoid maintainability issues, I would really recommend keeping these concerns in mind:</p>
<ul>
<li>always think concerns separation.</li>
<li>don&#39;t let your services grow big.</li>
<li>always return rich objects.</li>
<li>all your return objects should have the same structure.</li>
</ul>
<p>Happy refactoring!</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="banner service objects 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/banner-service-objects-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><h2 id="fat-models-and-skinny-controllers-right">Fat Models and skinny Controllers right?</h2>
<p>You know what they say about the MVC design pattern, keep your Controllers light.<br>So at the beginning of your project, you added oil and gears to your Models and it was rolling just fine. Even if I&#39;m not a big fan of the big Model that even makes coffee (sending an email, really?), I can say that you were in perfect harmony with the framework principles.<br>Well, a few iterations later, this idyllic codebase seems very far away and your Controllers and Models are way more &#39;200 line&#39;ish than they used to be.</p>
<span id="more-2821"></span>

<p>Service Objects is a good solution to extract some logic out of them by transferring code into simple services that handles only one thing. This way, you end up with maintainable, super understandable and separated critical code.<br>On this article I&#39;m focusing on Controllers, but the principles are the same for Models. Now, some may ask, why not using Controller Helpers instead?</p>
<p>My answer to that would be: don&#39;t choose, use both!</p>
<h2 id="service-object-and-controller-helper">Service object and Controller helper</h2>
<p>Controller Helpers do hold code shared between Controllers and are also a good way to keep slim Controllers. They are great to respect the DRY (Don&#39;t Repeat Yourself) principles. If you target the same workflows in many Controllers, you must consider putting this logic into a helper. The code you put here is a simple succession of actions you do and conditions you are evaluating. They are useful only if used by at least two Controllers, otherwise, you should think of some code refactoring.<br>Anyway, we often hear that backend logic should not belong to the Controller and just moving everything into a helper won&#39;t solve the problem.</p>
<p>For every operation tied to your business logic (calling an API, calculation) performed in this duplicated code or present in any Controller, you should definitely consider creating a service object for each chunk of logic.</p>
<p>Okay, now you know when to use a service object, but what is it exactly?</p>
<figure>
  <img style="width:50%;margin-left:25%" alt="A League of Legends poro" src="https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/048fa9cc-2f1d-4920-b29d-c80d7aafb488/d63wx6c-8af07a43-f112-489d-9087-e9c10077b7c8.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzA0OGZhOWNjLTJmMWQtNDkyMC1iMjlkLWM4MGQ3YWFmYjQ4OFwvZDYzd3g2Yy04YWYwN2E0My1mMTEyLTQ4OWQtOTA4Ny1lOWMxMDA3N2I3YzgucG5nIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.5MEQgeD-7_FV8NIh-rv8j8gw6FYgyQBuG_eOVUHq0Rc"/>
  <figcaption>A fluffy poro ! - Art by justduet on DeviantArt</figcaption>
</figure>

<p>A service object is a PORO. No, not that cute fluffy League of Legends NPC, but a Plain Old Ruby Object.<br>You just create a class not related to ActiveRecord (the RubyOnRails ORM) with it&#39;s own methods, put your code there, and WOW, you now have a PORO!<br>We will see how we construct it later, first we need to know where to put it in our project.</p>
<h2 id="break-it-to-rebuild-it">Break it to rebuild it</h2>
<p>First, let&#39;s take this Controller. One thing we can notice is an API call in this <code>get_weather</code> method and this should not be Controller business.</p>
<pre><code class="language-ruby">class HomeController &lt; ApplicationController
    require &#39;curb&#39;
    def index
    end

    def get_weather
        http = Curl.get(&quot;#{ENV[&quot;api_base&quot;]}#{ENV[&quot;api_key&quot;]}&quot;)
        if http.status = &quot;200 OK&quot;
            response_body = JSON.parse http.body_str
            @current_weather = response_body[&quot;weather&quot;][0][&quot;description&quot;]
            @current_temperature = &quot;#{(response_body[&quot;main&quot;][&quot;temp&quot;].to_f - 273.15).round(1)} °C&quot;
        else
            @current_weather = &quot;There was an error sorry: #{current_weather[:error]}&quot;
        end
    end
end
</code></pre>
<p>According to the name of the design pattern, we will create a <code>services</code> folder at <code>root_path/app/services/</code>.<br>Okay, looks like it&#39;s about getting weather informations so we will name another folder accordingly.<br>Finally, we can create our service object file. For this, we will be the most explicit and we will use something like <em>x_service.rb</em>.</p>
<p>Being precise on naming and using the <code>_service</code> suffix is here to help other code maintainers to easily understand what is the purpose of the service and where to find it in the project.</p>
<h3 id="skeleton">Skeleton</h3>
<p>This is how we should start every new service object. Here, we can note the import of the library &quot;ostruct&quot;. This allows us to use the OpenStruct object in order to return a rich object containing error messages and a <code>success?</code> method.</p>
<pre><code class="language-ruby">class FolderName::NameOfTheService
    require &quot;ostruct&quot;
    
    def initialize(params={})
        @params = params
    end

    def call
        begin
        rescue =&gt; exception
            OpenStruct.new(success?: false,
                           error: exception.message)
        else
            OpenStruct.new(success?: true, 
                           error: nil)
        end
    end

end
</code></pre>
<h3 id="filling-it-up">Filling it up</h3>
<p>Instead of just copying our Controller&#39;s code into our private method, we will use the wide known begin/rescue pattern to manage errors and will use it at our advantage to raise our own errors.  </p>
<pre><code class="language-ruby">class Weather::GetCurrentWeatherService
  require &quot;ostruct&quot;

    def initialize(params={})
      @params = params
    end

    def call
      @api_base = ENV[&quot;api_base&quot;]
      @api_key = ENV[&quot;api_key&quot;]

      begin
        http = Curl.get(&quot;#{@api_base}#{@api_key}&quot;)
        if http.status == &quot;200 OK&quot;
          response_body = JSON.parse http.body_str
          if response_body[&quot;weather&quot;] &amp;&amp; response_body[&quot;main&quot;]
            weather_string = response_body[&quot;weather&quot;][0][&quot;description&quot;]
            temperature = &quot;#{(response_body[&quot;main&quot;][&quot;temp&quot;].to_f - 273.15).round(1)} °C&quot;
          else
            raise
          end
        else
          raise
        end
      rescue =&gt; exception
          OpenStruct.new(success?: false,
                 error: exception.message)
        else
          OpenStruct.new(success?: true, 
                 weather_string: weather_string, 
                 temperature: temperature, 
                 error: nil)
        end
    end

end
</code></pre>
<h3 id="lets-refactor-this-controller">Let&#39;s refactor this Controller</h3>
<pre><code class="language-ruby">def get_weather
    current_weather = ::Weather::GetCurrentWeatherService.new.call(params: {})
    if current_weather.success?
        @current_weather = current_weather[:weather_string]
        @current_temperature = current_weather[:temperature]
    else
        @current_weather = &quot;There was an error sorry: #{current_weather[:error]}&quot;
    end
end
</code></pre>
<p>We simply call a new instance of our service in our Controller and use it&#39;s <code>success?</code> method to handle regular Controller rendering logic. Note the use of the prepending <code>::</code> it&#39;s for preventing the Controller to look for the service only in its own repository.<br>Here, the params argument is just an empty hash that I do not use but this was to show that, like every PORO, a service can take many parameters.</p>
<h2 id="this-pattern-is-so-great-but-ive-made-a-mess">This pattern is so great, but I&#39;ve made a mess!</h2>
<p>If our weather service was real, we would probably want to handle city search, forecast weather and so on. Maybe we would have extended our service object or created a bunch of others and now it&#39;s an obscure code to maintain and you can feel like you&#39;re drowning. No worries, it&#39;s just time for you to be rescued by NameSpacing!</p>
<p>In fact we already used it by putting our service in a weather folder in the first place. You should definitely classify all your new services by folders and never hesitate to create a sub folder when your folder holds too many service files.<br>If your services can be sliced by fields of usage or are really tied to a Model or Controller, create new folders and move your services under the corresponding ones.</p>
<p>For naming your folders, no master rule, but logic, efficiency, and consistency between the names.<br>Of course, you will need to rename your services. For instance, under a folder named <code>my_folder/my_folder_2</code> your <code>my_service</code> will be renamed <code>MyFolder::MyFolder2::MyService</code> and you will now use the same name in your Controllers to use them.</p>
<h2 id="so-so-or-not">So, SO or not?</h2>
<p>As you may have notice, I was mostly giving advices on how to implement it and never refer to the official documentation.<br>This is because this pattern does not have any convention and everyone can implement it its own way. In order to avoid maintainability issues, I would really recommend keeping these concerns in mind:</p>
<ul>
<li>always think concerns separation.</li>
<li>don&#39;t let your services grow big.</li>
<li>always return rich objects.</li>
<li>all your return objects should have the same structure.</li>
</ul>
<p>Happy refactoring!</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
