<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CK Lee</title>
    <description>The latest articles on DEV Community by CK Lee (@cklee).</description>
    <link>https://dev.to/cklee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F323170%2Fe3c3b1ff-409f-4d02-a773-9e6bbcc7d0f7.jpg</url>
      <title>DEV Community: CK Lee</title>
      <link>https://dev.to/cklee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cklee"/>
    <language>en</language>
    <item>
      <title>I log, you log, we log for the love of logs</title>
      <dc:creator>CK Lee</dc:creator>
      <pubDate>Thu, 04 Jun 2020 10:41:49 +0000</pubDate>
      <link>https://dev.to/cklee/i-log-you-log-we-log-for-the-love-of-logs-10jf</link>
      <guid>https://dev.to/cklee/i-log-you-log-we-log-for-the-love-of-logs-10jf</guid>
      <description>&lt;p&gt;The number of Docker containers deployed in our production boxes have steadily grown over the past 3 years. Last count - 284 containers running. I love logging but I'm shy to say we only just implemented centralised logging for these Docker containers yesterday. &lt;/p&gt;

&lt;p&gt;We are a profitable bootstrapped startup, and we don't have VC's money bags 💰 and unicorns 🦄 to chase. At TAGGUN, our top priority is to serve our customers by building &lt;a href="https://www.taggun.io/"&gt;receipt and invoice OCR scanning API&lt;/a&gt; that doesn't suck. So, the power of scarcity has deemed centralised logging as a YAGNI until a few days ago. &lt;/p&gt;

&lt;p&gt;I wished I had a cheatsheet to implement centralised logging for Docker containers. So, I'm sharing it here with you to save you time and money.&lt;/p&gt;

&lt;h2&gt;
  
  
  How is it done?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Jump to the Docker host&lt;/li&gt;
&lt;li&gt;Create or Modify the daemon.json found at /etc/docker&lt;/li&gt;
&lt;li&gt;You may need to &lt;code&gt;sudo -i&lt;/code&gt; first to access this area as the root user.&lt;/li&gt;
&lt;li&gt;Restart the docker daemon (this will take this box down for about 15-20 seconds) &lt;code&gt;sudo systemctl restart docker&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Verify the docker logger &lt;code&gt;docker info --format '{{.LoggingDriver}}'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker ps&lt;/code&gt; (This is to validate that docker has restarted without issues)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What configuration for daemon.json?
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "log-driver": "syslog",
    "log-opts": {
        "labels": "docker-&amp;lt;machine_name&amp;gt;",
        "tag": "docker-&amp;lt;machine_name&amp;gt;[{{.ImageName}}/{{.Name}}]",
        "mode": "non-blocking"
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Breakdown
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;log-driver is built in logging driver for docker; syslog is the one we're using because many server monitoring agents can easily read them from Syslogs.&lt;/li&gt;
&lt;li&gt;labels don't get logged to syslog it seems; left in because of docker best practices.&lt;/li&gt;
&lt;li&gt;tag does get logged to syslog. This is how you can let your log viewers knows what the application name, and processes are.&lt;/li&gt;
&lt;li&gt;mode is set to non-blocking which means a memory buffer is used for logging to syslog. if the log backpressure exceeds a certain point, logs will simply be dropped from this buffer, rather than blocking.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My recommended logging as a service platforms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.site24x7.com/"&gt;Site24x7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.loggly.com"&gt;Loggly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sematext.com/"&gt;Sematext&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;del&gt;Elastic Cloud&lt;/del&gt; (I love Elasticsearch and ELK stack. But my managed cluster is down too frequently)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[Cover photo by Andrew Ridley on Unsplash]&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Making Command-line interface (CLI) for fun and profit</title>
      <dc:creator>CK Lee</dc:creator>
      <pubDate>Fri, 24 Jan 2020 09:54:16 +0000</pubDate>
      <link>https://dev.to/cklee/making-command-line-interface-cli-for-fun-and-profit-3fj0</link>
      <guid>https://dev.to/cklee/making-command-line-interface-cli-for-fun-and-profit-3fj0</guid>
      <description>&lt;p&gt;Next time you have an idea 💡 "I know... Why don't I write a script to automate this thing?" Actually, you should not, you should write a &lt;em&gt;CLI&lt;/em&gt; instead.&lt;/p&gt;

&lt;p&gt;CLI has better structure than scripts. CLI uses flags and help text to avoid mistakes. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ moa --help
Moa makes it easier to run your local node.js apps.

USAGE
  $ moa

OPTIONS
  -c, --commands=commands  [default: start] commands to run.
  -h, --help               show CLI help
  -r, --root=root          [default: ../] root path to run.

DESCRIPTION
  ...
  Have some fun
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Scripts are messy. And can get out of control.&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://www.taggun.io"&gt;Taggun&lt;/a&gt;, we run a lot of node.js application.  We make APIs for receipt OCR scanning, by the way. So, I recommend &lt;a href="https://oclif.io/"&gt;oclif: The Open CLI Framework by Heroku&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create a new CLI
&lt;/h2&gt;

&lt;p&gt;Install &lt;a href="https://nodejs.org/en/"&gt;node.js&lt;/a&gt; first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start by scaffolding
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx oclif single moa
? npm package name (moa): moa
$ cd moa
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Modify your flags in &lt;code&gt;src\index.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MoaCommand.flags = {
  // add --help flag to show CLI version
  help: flags.help({char: 'h'}),
  commands: flags.string({char: 'c', description: 'commands to run. Comma-separated.', default: 'start'}),
  root: flags.string({char: 'r', description: 'root path to run.', default: '../'}),
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Modify your description in &lt;code&gt;src\index.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MoaCommand.description = `Moa makes it easier to run your local node.js apps.

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



&lt;h3&gt;
  
  
  Modify your command in &lt;code&gt;src\index.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MoaCommand extends Command {
  async run() {
    const {flags} = this.parse(MoaCommand)
    const commands = flags.commands.split(',')
    const {root} = flags
    find.file(/(?&amp;lt;!node_modules\/.*)\/package\.json$/, root, files =&amp;gt; {
      files.forEach(async file =&amp;gt; {
        const cwd = require('path').dirname(file)
        commands.forEach(async command =&amp;gt; {
          this.log(cwd, `npm run ${command}`)
          const npm = spawn('npm', ['run', command], {cwd})
          for await (const output of npm.stdout) {
            this.log(`${file}: ${output}`)
          }
        })
      })
    })
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this example, you will need to run &lt;code&gt;npm i find&lt;/code&gt; to install &lt;code&gt;find&lt;/code&gt; npm module.&lt;/p&gt;

&lt;p&gt;This simple CLI will look for all node.js application in the &lt;code&gt;[root]&lt;/code&gt; and run &lt;code&gt;npm run [command]&lt;/code&gt;. Great if you need to run multiple node.js application to start coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run it
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./bin/run -c start -c ../taggun/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Publish and share your CLI
&lt;/h3&gt;

&lt;p&gt;See &lt;a href="https://oclif.io/docs/releasing"&gt;https://oclif.io/docs/releasing&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
