{"id":867,"date":"2020-08-17T02:52:12","date_gmt":"2020-08-17T02:52:12","guid":{"rendered":"https:\/\/www.crccheck.com\/blog\/?p=867"},"modified":"2020-09-13T08:03:26","modified_gmt":"2020-09-13T08:03:26","slug":"code-review-writing-javascript-error-logs","status":"publish","type":"post","link":"https:\/\/www.crccheck.com\/blog\/code-review-writing-javascript-error-logs\/","title":{"rendered":"Code Review: Writing JavaScript error logs"},"content":{"rendered":"\n<pre class=\"wp-block-verse\"><span class=\"has-inline-color has-vivid-red-color\"><em>This is a \"Code review\" post. This is designed to be copy pasted into code reviews<\/em><\/span><\/pre>\n\n\n\n<p>I often see JavaScript code that looks like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const logger = Some logger like console, winston, bunyan, pino, debug, etc...\ntry {\n  \/\/ do something\n} catch (err) {\n  logger.error(err)\n  \/\/ handle error\n}<\/code><\/pre>\n\n\n\n<p>That&#8217;s a pretty big no-no because the only way to know where that error came from is from the error traceback. Tracebacks are hard to read, and you&#8217;re assuming that your traceback will even make it to your final logs. You may lose it via truncation or newlines.<\/p>\n\n\n\n<p>To fix it, all you have to do is to add a message:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const logger = Some logger like console, winston, bunyan, pino, debug, etc...\ntry {\n  \/\/ do something\n} catch (err) {\n  logger.error(\"abc.def: response isn't JSON\", { err })\n  \/\/ handle error\n}<\/code><\/pre>\n\n\n\n<p>It has a string that&#8217;s searchable, so you can search your logs for &#8220;abc.def&#8221; and get all of these errors. I&#8217;m pretty lazy and I don&#8217;t like to think about names so I just name it after the location and the function. <\/p>\n\n\n\n<p>If you <strong>know<\/strong> an error was related to something, I like to add a human readable message too, like &#8220;response isn&#8217;t JSON&#8221;. If you&#8217;re having trouble coming up with a message, that&#8217;s a code smell that your <code>try<\/code> block is covering too much code.<\/p>\n\n\n\n<p>To attach the original error, I add it to the JSON like <code>{ err }<\/code>. Most loggers look for <code>err<\/code> and transform it to get better quality logs. I think Bunyan made that popular in JavaScript and everyone copied it. <a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/github.com\/trentm\/node-bunyan#standard-serializers\">https:\/\/github.com\/trentm\/node-bunyan#standard-serializers<\/a><\/p>\n\n\n\n<p>You can and should stuff some more context in there too:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const logger = Some logger like console, winston, bunyan, pino, debug, etc...\ntry {\n  \/\/ do something\n  const resp = await fetch(url)\n  await resp.json()\n} catch (err) {\n  logger.error(\"abc.def: response isn't JSON\", { err, url })\n}<\/code><\/pre>\n\n\n\n<p>The goal is to have all the information you need to re-create the error locally. If you use Sentry, you&#8217;ll be used to this <a href=\"https:\/\/docs.sentry.io\/enriching-error-data\/additional-data\/#extra-context\">https:\/\/docs.sentry.io\/enriching-error-data\/additional-data\/#extra-context<\/a>. Unlike other languages, JavaScript doesn&#8217;t have local variables in errors, so we have to do this manually.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I often see JavaScript code that looks like: That&#8217;s a pretty big no-no because the only way to know where that error came from is from the error traceback. Tracebacks are hard to read, and you&#8217;re assuming that your traceback will even make it to your final logs. You may lose it via truncation or&hellip;<\/p>\n <a href=\"https:\/\/www.crccheck.com\/blog\/code-review-writing-javascript-error-logs\/\" title=\"Code Review: Writing JavaScript error logs\" class=\"entry-more-link\"><span>Read More<\/span> <span class=\"screen-reader-text\">Code Review: Writing JavaScript error logs<\/span><\/a>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[85,4],"tags":[12],"class_list":["entry","author-showmewhatyougot","post-867","post","type-post","status-publish","format-standard","category-code-review","category-technical","tag-js"],"_links":{"self":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/867","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/comments?post=867"}],"version-history":[{"count":5,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/867\/revisions"}],"predecessor-version":[{"id":881,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/867\/revisions\/881"}],"wp:attachment":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/media?parent=867"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/categories?post=867"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/tags?post=867"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}