{"componentChunkName":"component---src-templates-best-practice-detail-tsx","path":"/best-practice/2020-06-03-scf-log-retrieval","result":{"data":{"currentBlog":{"id":"a8cfef63-eb3c-52e1-b744-9fa185998898","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/202063/1591174404685-%E4%BA%91%E5%87%BD%E6%95%B0%E6%97%A5%E5%BF%97%E6%A3%80%E7%B4%A2.jpg","authors":["李婷"],"categories":["best-practice"],"date":"2020-06-03T00:00:00.000Z","title":"腾讯云云函数 SCF 日志检索最佳实践","description":"借助云函数监控日志快速发现并定位问题","authorslink":null,"translators":null,"translatorslink":null,"tags":["云函数","日志检索"],"keywords":"Serverless,scf,Serverless Framework","outdated":null},"wordCount":{"words":129,"sentences":36,"paragraphs":36},"fileAbsolutePath":"/opt/build/repo/content/best-practice/2020-06-03-scf-log-retrieval.md","fields":{"slug":"/best-practice/2020-06-03-scf-log-retrieval/","keywords":["python","serverless","云函数","日志","检索","关键词","serverlesscloud","函数","请求","RequestId"]},"html":"<p>开发者在云函数的开发调试、在线运维过程中，难免会遇到函数调用失败需要定位问题的情况，通常我们使用日志作为主要排障手段。</p>\n<p>在云函数控制台中，我们可以看到包含函数调用状态的日志列表，直接筛选可过滤查看所有调用失败的日志。</p>\n<p>如果我们能够从网关返回信息中拿到某个失败请求的 RequestId ，我们还可以根据 RequestId 检索指定请求的日志。</p>\n<p><img src=\"https://img.serverlesscloud.cn/202063/1591168127983-6.jpg\"></p>\n<p>这是最基础的日志检索使用方法。</p>\n<p><strong>实际定位问题的过程中，有可能出现以下几种场景：</strong></p>\n<ul>\n<li>函数里的部分异常有进行捕获，但函数的调用状态依然是成功，此时怎么找到已捕获的异常？</li>\n<li>函数错误调用非常多，我只想查看某些指定模块的日志信息怎么办？</li>\n<li>收到告警提示我函数运行时间超过 x 秒，我如何迅速找到指定运行时长范围的调用日志？</li>\n<li>我要查看的业务日志包含多个不同的关键词，想要一次性找到多个关键词所在的日志怎么办？</li>\n</ul>\n<p>针对以上场景，我们可以利用「高级日志」功能解决上述全部问题。</p>\n<h2 id=\"高级日志如何使用\"><a href=\"#%E9%AB%98%E7%BA%A7%E6%97%A5%E5%BF%97%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8\" aria-label=\"高级日志如何使用 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>高级日志如何使用</h2>\n<p>下面给大家分享一下<code class=\"language-text\">已捕获的异常</code>，<code class=\"language-text\">查找函数运行时间大于 x 的请求</code>，<code class=\"language-text\">关键词组合检索</code>中如何使用高级日志。</p>\n<h3 id=\"1-已捕获的异常\"><a href=\"#1-%E5%B7%B2%E6%8D%95%E8%8E%B7%E7%9A%84%E5%BC%82%E5%B8%B8\" aria-label=\"1 已捕获的异常 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. 已捕获的异常</h3>\n<p>云函数比较多的使用场景是和 API 网关组合使用实现 REST API ，以下我们结合一个实际的业务场景说明如何使用高级日志。</p>\n<p>以下模拟一个 HTTP PUT 请求实现教师录入学生信息的功能。</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"19805109458245005000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def teacher_put():\n    print('insert info')\n    try:\n        fh = open(&quot;/tmp/testfile&quot;, &quot;w&quot;)\n        fh.write(&quot;students info xxxx&quot;)\n    except IOError:\n        print(&quot;Error: cannot find the file or open file failed&quot;)\n    else:\n        print(&quot;write info success&quot;)\n        fh.close()\n        return('teacher_put success')\n\n\ndef main_handler(event, context):\n    print(str(event))\n    if event[&quot;pathParameters&quot;][&quot;user_type&quot;] == &quot;teacher&quot;:\n        if event[&quot;pathParameters&quot;][&quot;action&quot;] == &quot;get&quot;:\n            return teacher_get()\n        if event[&quot;pathParameters&quot;][&quot;action&quot;] == &quot;put&quot;:\n            return teacher_put()`, `19805109458245005000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">teacher_put</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'insert info'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        fh <span class=\"token operator\">=</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/tmp/testfile\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"w\"</span><span class=\"token punctuation\">)</span>\n        fh<span class=\"token punctuation\">.</span>write<span class=\"token punctuation\">(</span><span class=\"token string\">\"students info xxxx\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">except</span> IOError<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Error: cannot find the file or open file failed\"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"write info success\"</span><span class=\"token punctuation\">)</span>\n        fh<span class=\"token punctuation\">.</span>close<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span><span class=\"token punctuation\">(</span><span class=\"token string\">'teacher_put success'</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">str</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"pathParameters\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"user_type\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"teacher\"</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">if</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"pathParameters\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"action\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"get\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span> teacher_get<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"pathParameters\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"action\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"put\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span> teacher_put<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>由于上面写文件时的 IO 异常已被捕获，所以当找不到文件时，函数调用结果依然为成功，API 请求返回 null 。如果使用普通调用日志功能，需要逐条查看日志，这将会非常麻烦。</p>\n<p>我们在代码捕获异常时有打印 Error 信息，在高级日志里可以直接检索该关键词：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202063/1591168216248-2.png\"></p>\n<p>如果想查看包含该请求的完整日志，则点击该条日志的 RequestId 即可：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202063/1591168129971-6.jpg\"></p>\n<p>上面讲述了如何查找已被捕获的异常，直接检索捕获时打印的关键词即可, 日志输出方法没有特殊要求，使用运行时原生日志即可。</p>\n<h3 id=\"2-查找函数运行时间大于-x-的请求\"><a href=\"#2-%E6%9F%A5%E6%89%BE%E5%87%BD%E6%95%B0%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%E5%A4%A7%E4%BA%8E-x-%E7%9A%84%E8%AF%B7%E6%B1%82\" aria-label=\"2 查找函数运行时间大于 x 的请求 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. 查找函数运行时间大于 x 的请求</h3>\n<p>如果我们收到告警或通过监控图表查看到某个函数的运行时间异常，如何迅速找到这些日志呢？</p>\n<p>高级日志里提供了运行时间检索的方法，比如我们想查找运行时间大于 150ms 的日志，我们可以在检索框输入 <code class=\"language-text\">SCF_Duration&gt;150</code>，即可找出该时间范围的日志。</p>\n<p><img src=\"https://img.serverlesscloud.cn/202063/1591168129314-6.jpg\"></p>\n<p>时间范围和关键词检索可组合使用，在上述示例中会将所有日志都过滤出来。</p>\n<p>如果我们只想查看有多少请求的运行时间是大于 150 ms ，我们可以组合关键词过滤 <code class=\"language-text\">SCF_Duration&gt;150 and &quot;Report RequestId&quot;</code> 进行检索：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202063/1591168128785-6.jpg\"></p>\n<p>上述表达式的意思是，过滤运行时间大于 150 ms 且 包含 Report RequestId 关键词的日志。Report RequestId这一行是函数每次请求结束后系统打印的语句，所以可以用它来达到筛选唯一请求日志的作用。</p>\n<p>如果想过滤出 <code class=\"language-text\">150&lt;运行时间≤300</code> 的日志，则可以使用 <code class=\"language-text\">SCF_Duration in (150 300]</code>。</p>\n<h3 id=\"3-关键词组合检索\"><a href=\"#3-%E5%85%B3%E9%94%AE%E8%AF%8D%E7%BB%84%E5%90%88%E6%A3%80%E7%B4%A2\" aria-label=\"3 关键词组合检索 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3. 关键词组合检索</h3>\n<p>如果我们想同时检索多个关键词，比如 <code class=\"language-text\">error</code>，<code class=\"language-text\">userid</code>，<code class=\"language-text\">region</code>我们可以使用 <code class=\"language-text\">and</code> 或者 <code class=\"language-text\">or</code> 连接这些关键词。</p>\n<p>如想要过滤出同时包含这些关键词的日志，则可以使用 <code class=\"language-text\">error and userid and region</code> 。</p>\n<p>如想要过滤出包含任一关键词的日志，则可以使用 <code class=\"language-text\">error or userid or region</code>。</p>\n<p>高级日志服务提供了丰富的检索语法，可参考<a href=\"https://cloud.tencent.com/document/product/583/40964\">日志检索语法教程</a></p>\n<hr>\n<div id='scf-deploy-iframe-or-md'></div>\n<hr>\n<blockquote>\n<p><strong>传送门：</strong></p>\n<ul>\n<li>GitHub: <a href=\"https://github.com/serverless/serverless/blob/master/README_CN.md\">github.com/serverless</a></li>\n<li>官网：<a href=\"https://serverless.com/\">serverless.com</a></li>\n</ul>\n</blockquote>\n<p>欢迎访问：<a href=\"https://serverlesscloud.cn/\">Serverless 中文网</a>，您可以在 <a href=\"https://serverlesscloud.cn/best-practice\">最佳实践</a> 里体验更多关于 Serverless 应用的开发！</p>","tableOfContents":"<ul>\n<li>\n<p><a href=\"/best-practice/2020-06-03-scf-log-retrieval/#%E9%AB%98%E7%BA%A7%E6%97%A5%E5%BF%97%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8\">高级日志如何使用</a></p>\n<ul>\n<li><a href=\"/best-practice/2020-06-03-scf-log-retrieval/#1-%E5%B7%B2%E6%8D%95%E8%8E%B7%E7%9A%84%E5%BC%82%E5%B8%B8\">1. 已捕获的异常</a></li>\n<li><a href=\"/best-practice/2020-06-03-scf-log-retrieval/#2-%E6%9F%A5%E6%89%BE%E5%87%BD%E6%95%B0%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%E5%A4%A7%E4%BA%8E-x-%E7%9A%84%E8%AF%B7%E6%B1%82\">2. 查找函数运行时间大于 x 的请求</a></li>\n<li><a href=\"/best-practice/2020-06-03-scf-log-retrieval/#3-%E5%85%B3%E9%94%AE%E8%AF%8D%E7%BB%84%E5%90%88%E6%A3%80%E7%B4%A2\">3. 关键词组合检索</a></li>\n</ul>\n</li>\n</ul>"},"previousBlog":{"id":"a3ca49f4-36aa-582e-b85a-f280e69ef07f","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/202064/1591262740524-%E6%96%87%E6%9C%AC%E7%BF%BB%E8%AF%91.jpg","authors":["Tina"],"categories":["best-practice"],"date":"2020-06-04T00:00:00.000Z","title":"使用 Serverless Framework Express 组件快速创建文本翻译工具","description":"通过 Express Component 实现一款文本翻译工具","authorslink":null,"translators":null,"translatorslink":null,"tags":["Serverless","文本翻译"],"keywords":"Serverless,scf,Serverless Framework","outdated":null},"wordCount":{"words":187,"sentences":43,"paragraphs":43},"fileAbsolutePath":"/opt/build/repo/content/best-practice/2020-06-04-sf-express-component-translate.md","fields":{"slug":"/best-practice/2020-06-04-sf-express-component-translate/","keywords":["serverless","spa","无服务器","云函数","serverless","Serverless","tencent","github","次数","errors"]}},"nextBlog":{"id":"e11d0eba-c207-538d-9f54-5407cd8e8054","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/202061/1591005673237-%E4%BA%A7%E5%93%81%E8%BF%81%E7%A7%BB%E5%AE%9E%E8%B7%B5.jpg","authors":["董文强"],"categories":["best-practice"],"date":"2020-06-01T00:00:00.000Z","title":"江娱互动「世界争霸」产品迁移至腾讯云云函数","description":"腾讯云云函数，以保障性能为前提，同时做到省事和省钱，成为江娱互动的不二选择。","authorslink":null,"translators":null,"translatorslink":null,"tags":["Serverless","云函数"],"keywords":"Serverless,scf,Serverless Framework","outdated":null},"wordCount":{"words":444,"sentences":62,"paragraphs":62},"fileAbsolutePath":"/opt/build/repo/content/best-practice/2020-06-01-scf-case.md","fields":{"slug":"/best-practice/2020-06-01-scf-case/","keywords":["php","serverless","云函数","函数","日志","网关","腾讯","serverlesscloud","需要","代码"]}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"blogId":"a8cfef63-eb3c-52e1-b744-9fa185998898","previousBlogId":"a3ca49f4-36aa-582e-b85a-f280e69ef07f","nextBlogId":"e11d0eba-c207-538d-9f54-5407cd8e8054"}}}