PageRenderTime 28ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/articles/20160711-django-logging.html

https://github.com/pfarmer/pfarmer.github.com
HTML | 323 lines | 287 code | 34 blank | 2 comment | 0 complexity | 23cf6281c64bb088e1effe1ca54e217c MD5 | raw file
  1. <!DOCTYPE html>
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>Django logging (redux) &mdash; projectchilli.com</title>
  6. <link rel="stylesheet" href="../_static/basic.css" type="text/css" />
  7. <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
  8. <link rel="stylesheet" href="../_static/my-styles.css" type="text/css" />
  9. <link rel="stylesheet" href="../_static/bootswatch-3.3.6/united/bootstrap.min.css" type="text/css" />
  10. <link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
  11. <script type="text/javascript">
  12. var DOCUMENTATION_OPTIONS = {
  13. URL_ROOT: '../',
  14. VERSION: '0.4.9',
  15. COLLAPSE_INDEX: false,
  16. FILE_SUFFIX: '.html',
  17. HAS_SOURCE: true
  18. };
  19. </script>
  20. <script type="text/javascript" src="../_static/jquery.js"></script>
  21. <script type="text/javascript" src="../_static/underscore.js"></script>
  22. <script type="text/javascript" src="../_static/doctools.js"></script>
  23. <script type="text/javascript" src="../_static/js/jquery-1.11.0.min.js"></script>
  24. <script type="text/javascript" src="../_static/js/jquery-fix.js"></script>
  25. <script type="text/javascript" src="../_static/bootstrap-3.3.6/js/bootstrap.min.js"></script>
  26. <script type="text/javascript" src="../_static/bootstrap-sphinx.js"></script>
  27. <link rel="author" title="About these documents" href="../about.html" />
  28. <link rel="top" title="projectchilli.com" href="../index.html" />
  29. <meta charset='utf-8'>
  30. <meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
  31. <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
  32. <meta name="apple-mobile-web-app-capable" content="yes">
  33. </head>
  34. <body>
  35. <div id="navbar" class="navbar navbar-default navbar-fixed-top">
  36. <div class="container">
  37. <div class="navbar-header">
  38. <!-- .btn-navbar is used as the toggle for collapsed navbar content -->
  39. <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
  40. <span class="icon-bar"></span>
  41. <span class="icon-bar"></span>
  42. <span class="icon-bar"></span>
  43. </button>
  44. <a class="navbar-brand" href="../index.html">
  45. projectchilli.com</a>
  46. <!-- <span class="navbar-text navbar-version pull-left"><b>0.4.9</b></span> -->
  47. </div>
  48. <div class="collapse navbar-collapse nav-collapse">
  49. <ul class="nav navbar-nav">
  50. <li class="dropdown globaltoc-container">
  51. <a role="button"
  52. id="dLabelGlobalToc"
  53. data-toggle="dropdown"
  54. data-target="#"
  55. href="../index.html">Site <b class="caret"></b></a>
  56. <ul class="dropdown-menu globaltoc"
  57. role="menu"
  58. aria-labelledby="dLabelGlobalToc"></ul>
  59. </li>
  60. <li class="dropdown">
  61. <a role="button"
  62. id="dLabelLocalToc"
  63. data-toggle="dropdown"
  64. data-target="#"
  65. href="#">Page <b class="caret"></b></a>
  66. <ul class="dropdown-menu localtoc"
  67. role="menu"
  68. aria-labelledby="dLabelLocalToc"><ul>
  69. <li><a class="reference internal" href="#">Django logging (redux)</a><ul>
  70. <li><a class="reference internal" href="#set-debug-to-false-in-your-settings-py-file">1. Set DEBUG to False in your settings.py file:</a></li>
  71. <li><a class="reference internal" href="#update-the-logging-section-in-settings-py">2. Update the logging section in settings.py:</a><ul>
  72. <li><a class="reference internal" href="#formatters">formatters</a></li>
  73. <li><a class="reference internal" href="#handlers">handlers</a></li>
  74. <li><a class="reference internal" href="#loggers">loggers</a></li>
  75. </ul>
  76. </li>
  77. <li><a class="reference internal" href="#if-you-are-using-celery-in-the-application">3. If you are using celery in the application.</a></li>
  78. <li><a class="reference internal" href="#make-sure-you-have-a-500-html-template-in-place">4. Make sure you have a 500.html template in place.</a></li>
  79. <li><a class="reference internal" href="#the-added-bonus">5. The added bonus....</a></li>
  80. <li><a class="reference internal" href="#then-use-code-like-this-to-log-messages">6. Then use code like this to log messages:</a></li>
  81. </ul>
  82. </li>
  83. </ul>
  84. </ul>
  85. </li>
  86. <li class="hidden-sm">
  87. <div id="sourcelink">
  88. <a href="../_sources/articles/20160711-django-logging.txt"
  89. rel="nofollow">Source</a>
  90. </div></li>
  91. </ul>
  92. <form class="navbar-form navbar-right" action="../search.html" method="get">
  93. <div class="form-group">
  94. <input type="text" name="q" class="form-control" placeholder="Search" />
  95. </div>
  96. <input type="hidden" name="check_keywords" value="yes" />
  97. <input type="hidden" name="area" value="default" />
  98. </form>
  99. </div>
  100. </div>
  101. </div>
  102. <div class="container">
  103. <div class="row">
  104. <div class="col-md-12 content">
  105. <div class="section" id="django-logging-redux">
  106. <h1>Django logging (redux)</h1>
  107. <p><strong>Date</strong>: 2016-07-11 - <strong>Categories</strong>: <a class="reference external" href="/categories/django.html">django</a>, <a class="reference external" href="/categories/python.html">python</a></p>
  108. <div class="admonition note">
  109. <p class="first admonition-title">Note</p>
  110. <p class="last">This is a rewrite of the blog post I wrote in 2012.</p>
  111. </div>
  112. <p>Having spent a number of years writing django web applications (a number of which are in production) I&#8217;ve learnt a few things about how to get good logging. So here is my current logging setup. I don&#8217;t claim to be an expert, but this setup works for me, and hopefully will work for you, or at least get you started.</p>
  113. <div class="section" id="set-debug-to-false-in-your-settings-py-file">
  114. <h2>1. Set DEBUG to False in your settings.py file:</h2>
  115. <div class="code python highlight-python"><div class="highlight"><pre><span></span><span class="n">DEBUG</span><span class="o">=</span><span class="bp">False</span>
  116. </pre></div>
  117. </div>
  118. <p>This prevents the details exception data from being displayed on screen. To re-iterate what the django documentation website says: <strong>NEVER</strong> <a class="footnote-reference" href="#f1" id="id1">[1]</a> deploy a production site with <tt class="docutils literal"><span class="pre">DEBUG=True</span></tt>.</p>
  119. </div>
  120. <div class="section" id="update-the-logging-section-in-settings-py">
  121. <h2>2. Update the logging section in settings.py:</h2>
  122. <div class="code python highlight-python"><div class="highlight"><pre><span></span><span class="n">LOGGING</span> <span class="o">=</span> <span class="p">{</span>
  123. <span class="s1">&#39;version&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
  124. <span class="s1">&#39;disable_existing_loggers&#39;</span><span class="p">:</span> <span class="bp">False</span><span class="p">,</span>
  125. <span class="s1">&#39;formatters&#39;</span><span class="p">:</span> <span class="p">{</span>
  126. <span class="s1">&#39;verbose&#39;</span><span class="p">:</span> <span class="p">{</span>
  127. <span class="s1">&#39;format&#39;</span><span class="p">:</span> <span class="s1">&#39;</span><span class="si">%(levelname)s</span><span class="s1"> </span><span class="si">%(asctime)s</span><span class="s1"> </span><span class="si">%(module)s</span><span class="s1"> </span><span class="si">%(process)d</span><span class="s1"> </span><span class="si">%(thread)d</span><span class="s1"> </span><span class="si">%(message)s</span><span class="s1">&#39;</span>
  128. <span class="p">},</span>
  129. <span class="s1">&#39;simple&#39;</span><span class="p">:</span> <span class="p">{</span>
  130. <span class="s1">&#39;format&#39;</span><span class="p">:</span> <span class="s1">&#39;</span><span class="si">%(levelname)s</span><span class="s1"> </span><span class="si">%(message)s</span><span class="s1">&#39;</span>
  131. <span class="p">},</span>
  132. <span class="s1">&#39;standard&#39;</span><span class="p">:</span> <span class="p">{</span>
  133. <span class="s1">&#39;format&#39;</span><span class="p">:</span> <span class="s1">&#39;</span><span class="si">%(asctime)s</span><span class="s1"> [</span><span class="si">%(levelname)s</span><span class="s1">] </span><span class="si">%(name)s</span><span class="s1">:</span><span class="si">%(lineno)d</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">&#39;</span>
  134. <span class="p">},</span>
  135. <span class="p">},</span>
  136. <span class="s1">&#39;handlers&#39;</span><span class="p">:</span> <span class="p">{</span>
  137. <span class="s1">&#39;null&#39;</span><span class="p">:</span> <span class="p">{</span>
  138. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  139. <span class="s1">&#39;class&#39;</span><span class="p">:</span> <span class="s1">&#39;logging.NullHandler&#39;</span><span class="p">,</span>
  140. <span class="p">},</span>
  141. <span class="s1">&#39;default_error&#39;</span><span class="p">:</span> <span class="p">{</span>
  142. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;ERROR&#39;</span><span class="p">,</span>
  143. <span class="s1">&#39;class&#39;</span><span class="p">:</span> <span class="s1">&#39;logging.handlers.RotatingFileHandler&#39;</span><span class="p">,</span>
  144. <span class="s1">&#39;filename&#39;</span><span class="p">:</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">/logs/error.log&#39;</span> <span class="o">%</span> <span class="n">BASE_DIR</span><span class="p">,</span>
  145. <span class="s1">&#39;maxBytes&#39;</span><span class="p">:</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">50</span><span class="p">,</span> <span class="c1"># 50 MB</span>
  146. <span class="s1">&#39;backupCount&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
  147. <span class="s1">&#39;formatter&#39;</span><span class="p">:</span> <span class="s1">&#39;standard&#39;</span><span class="p">,</span>
  148. <span class="p">},</span>
  149. <span class="s1">&#39;default_info&#39;</span><span class="p">:</span> <span class="p">{</span>
  150. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;INFO&#39;</span><span class="p">,</span>
  151. <span class="s1">&#39;class&#39;</span><span class="p">:</span> <span class="s1">&#39;logging.handlers.RotatingFileHandler&#39;</span><span class="p">,</span>
  152. <span class="s1">&#39;filename&#39;</span><span class="p">:</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">/logs/default.log&#39;</span> <span class="o">%</span> <span class="n">BASE_DIR</span><span class="p">,</span>
  153. <span class="s1">&#39;maxBytes&#39;</span><span class="p">:</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">50</span><span class="p">,</span> <span class="c1"># 50 MB</span>
  154. <span class="s1">&#39;backupCount&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
  155. <span class="s1">&#39;formatter&#39;</span><span class="p">:</span> <span class="s1">&#39;standard&#39;</span><span class="p">,</span>
  156. <span class="p">},</span>
  157. <span class="s1">&#39;default_debug&#39;</span><span class="p">:</span> <span class="p">{</span>
  158. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  159. <span class="s1">&#39;class&#39;</span><span class="p">:</span> <span class="s1">&#39;logging.handlers.RotatingFileHandler&#39;</span><span class="p">,</span>
  160. <span class="s1">&#39;filename&#39;</span><span class="p">:</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">/logs/default-debug.log&#39;</span> <span class="o">%</span> <span class="n">BASE_DIR</span><span class="p">,</span>
  161. <span class="s1">&#39;maxBytes&#39;</span><span class="p">:</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">50</span><span class="p">,</span> <span class="c1"># 50 MB</span>
  162. <span class="s1">&#39;backupCount&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
  163. <span class="s1">&#39;formatter&#39;</span><span class="p">:</span> <span class="s1">&#39;standard&#39;</span><span class="p">,</span>
  164. <span class="p">},</span>
  165. <span class="s1">&#39;console&#39;</span><span class="p">:</span> <span class="p">{</span>
  166. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  167. <span class="s1">&#39;class&#39;</span><span class="p">:</span> <span class="s1">&#39;logging.StreamHandler&#39;</span><span class="p">,</span>
  168. <span class="s1">&#39;formatter&#39;</span><span class="p">:</span> <span class="s1">&#39;standard&#39;</span>
  169. <span class="p">},</span>
  170. <span class="s1">&#39;request_handler&#39;</span><span class="p">:</span> <span class="p">{</span>
  171. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  172. <span class="s1">&#39;class&#39;</span><span class="p">:</span> <span class="s1">&#39;logging.handlers.RotatingFileHandler&#39;</span><span class="p">,</span>
  173. <span class="s1">&#39;filename&#39;</span><span class="p">:</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">/logs/django_request.log&#39;</span> <span class="o">%</span> <span class="n">BASE_DIR</span><span class="p">,</span>
  174. <span class="s1">&#39;maxBytes&#39;</span><span class="p">:</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">50</span><span class="p">,</span> <span class="c1"># 50 MB</span>
  175. <span class="s1">&#39;backupCount&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
  176. <span class="s1">&#39;formatter&#39;</span><span class="p">:</span> <span class="s1">&#39;standard&#39;</span><span class="p">,</span>
  177. <span class="p">},</span>
  178. <span class="s1">&#39;celery_handler&#39;</span><span class="p">:</span> <span class="p">{</span>
  179. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  180. <span class="s1">&#39;class&#39;</span><span class="p">:</span> <span class="s1">&#39;logging.handlers.RotatingFileHandler&#39;</span><span class="p">,</span>
  181. <span class="s1">&#39;filename&#39;</span><span class="p">:</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">/logs/celery.log&#39;</span> <span class="o">%</span> <span class="n">BASE_DIR</span><span class="p">,</span>
  182. <span class="s1">&#39;maxBytes&#39;</span><span class="p">:</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">50</span><span class="p">,</span> <span class="c1"># 50 MB</span>
  183. <span class="s1">&#39;backupCount&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
  184. <span class="s1">&#39;formatter&#39;</span><span class="p">:</span> <span class="s1">&#39;standard&#39;</span><span class="p">,</span>
  185. <span class="p">},</span>
  186. <span class="p">},</span>
  187. <span class="s1">&#39;loggers&#39;</span><span class="p">:</span> <span class="p">{</span>
  188. <span class="s1">&#39;&#39;</span><span class="p">:</span> <span class="p">{</span>
  189. <span class="s1">&#39;handlers&#39;</span><span class="p">:</span> <span class="p">[</span><span class="s1">&#39;default_info&#39;</span><span class="p">,</span> <span class="s1">&#39;default_debug&#39;</span><span class="p">,</span> <span class="s1">&#39;default_error&#39;</span><span class="p">],</span>
  190. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  191. <span class="s1">&#39;propagate&#39;</span><span class="p">:</span> <span class="bp">True</span>
  192. <span class="p">},</span>
  193. <span class="s1">&#39;django.request&#39;</span><span class="p">:</span> <span class="p">{</span> <span class="c1"># Stop SQL debug from logging to main logger</span>
  194. <span class="s1">&#39;handlers&#39;</span><span class="p">:</span> <span class="p">[</span><span class="s1">&#39;request_handler&#39;</span><span class="p">],</span>
  195. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  196. <span class="s1">&#39;propagate&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
  197. <span class="p">},</span>
  198. <span class="s1">&#39;requests.packages.urllib3.connectionpool&#39;</span><span class="p">:</span> <span class="p">{</span>
  199. <span class="s1">&#39;handlers&#39;</span><span class="p">:</span> <span class="p">[</span><span class="s1">&#39;null&#39;</span><span class="p">],</span>
  200. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  201. <span class="s1">&#39;propagate&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
  202. <span class="p">},</span>
  203. <span class="s1">&#39;celery&#39;</span><span class="p">:</span> <span class="p">{</span>
  204. <span class="s1">&#39;handlers&#39;</span><span class="p">:</span> <span class="p">[</span><span class="s1">&#39;celery_handler&#39;</span><span class="p">],</span>
  205. <span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span>
  206. <span class="s1">&#39;propagate&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
  207. <span class="p">},</span>
  208. <span class="p">}</span>
  209. <span class="p">}</span>
  210. </pre></div>
  211. </div>
  212. <div class="section" id="formatters">
  213. <h3>formatters</h3>
  214. <p>The <tt class="docutils literal"><span class="pre">formatters</span></tt> define how the message should look when they are written, I have three examples in my config, <tt class="docutils literal"><span class="pre">verbose</span></tt>, <tt class="docutils literal"><span class="pre">simple</span></tt> and <tt class="docutils literal"><span class="pre">standard</span></tt>, the <tt class="docutils literal"><span class="pre">standard</span></tt> format is one used throughout the rest of the config and produces log entries which look like this::</p>
  215. <div class="highlight-python"><div class="highlight"><pre><span></span>2011-11-16 23:02:32,339 [DEBUG] api.views:125: API login attempt for pfarmer
  216. </pre></div>
  217. </div>
  218. </div>
  219. <div class="section" id="handlers">
  220. <h3>handlers</h3>
  221. <p>The <tt class="docutils literal"><span class="pre">handlers</span></tt> determine how and where the log message is displayed/written.</p>
  222. </div>
  223. <div class="section" id="loggers">
  224. <h3>loggers</h3>
  225. <p>The <tt class="docutils literal"><span class="pre">loggers</span></tt> provide the final plumbing between the <tt class="docutils literal"><span class="pre">formatters</span></tt>, <tt class="docutils literal"><span class="pre">handlers</span></tt> and the actual log messages.</p>
  226. <p>For more information on how logging works see the <a class="reference external" href="https://docs.python.org/2/library/logging.html">Python docs</a>.</p>
  227. <p>Now when some code causes an exception, the traceback should appear in <strong>error.log</strong> (and django_request.log).</p>
  228. </div>
  229. </div>
  230. <div class="section" id="if-you-are-using-celery-in-the-application">
  231. <h2>3. If you are using celery in the application.</h2>
  232. <p>Add this to the settings file:</p>
  233. <div class="code python highlight-python"><div class="highlight"><pre><span></span><span class="n">CELERYD_HIJACK_ROOT_LOGGER</span> <span class="o">=</span> <span class="bp">False</span>
  234. </pre></div>
  235. </div>
  236. </div>
  237. <div class="section" id="make-sure-you-have-a-500-html-template-in-place">
  238. <h2>4. Make sure you have a 500.html template in place.</h2>
  239. </div>
  240. <div class="section" id="the-added-bonus">
  241. <h2>5. The added bonus....</h2>
  242. <p>The added bonus is you can use the standard python logging module to log during view execution, add the following to each of your views.py:</p>
  243. <div class="code python highlight-python"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
  244. <span class="n">log</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
  245. </pre></div>
  246. </div>
  247. </div>
  248. <div class="section" id="then-use-code-like-this-to-log-messages">
  249. <h2>6. Then use code like this to log messages:</h2>
  250. <div class="code python highlight-python"><div class="highlight"><pre><span></span>log.debug(&quot;API login attempt for %s&quot; request.GET[&#39;user&#39;])
  251. </pre></div>
  252. </div>
  253. <p>This will appear in the log like this::</p>
  254. <div class="highlight-python"><div class="highlight"><pre><span></span>2011-11-16 23:02:32,339 [DEBUG] api.views: API login attempt for pfarmer
  255. </pre></div>
  256. </div>
  257. <p class="rubric">Footnotes</p>
  258. <table class="docutils footnote" frame="void" id="f1" rules="none">
  259. <colgroup><col class="label" /><col /></colgroup>
  260. <tbody valign="top">
  261. <tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td><a class="reference external" href="https://docs.djangoproject.com/en/1.9/ref/settings/#debug">https://docs.djangoproject.com/en/1.9/ref/settings/#debug</a></td></tr>
  262. </tbody>
  263. </table>
  264. </div>
  265. </div>
  266. </div>
  267. </div>
  268. </div>
  269. <footer class="footer">
  270. <div class="container">
  271. <p class="pull-right">
  272. <a href="#">Back to top</a>
  273. </p>
  274. <p>
  275. &copy; Copyright 2011-2016, Peter Farmer.<br/>
  276. Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.1.<br/>
  277. </p>
  278. </div>
  279. </footer>
  280. <script>
  281. (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  282. (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  283. m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  284. })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
  285. ga('create', 'UA-322710-20', 'auto');
  286. ga('send', 'pageview');
  287. </script>
  288. </body>
  289. </html>