Sentry(v20.12.1) K8S 云原生架构探索,JavaScript Data Management(问题分组篇)

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: Sentry(v20.12.1) K8S 云原生架构探索,JavaScript Data Management(问题分组篇)

SDK Fingerprinting



在受支持的 SDK 中,可以覆盖 Sentry 的默认分组,该分组将 fingerprint 属性作为字符串数组传递。fingerprint 数组的长度不受限制。这类似于 fingerprint rules functionality,它总是可用的,并可以实现类似的结果。


Basic Example


在最基本的情况下,值直接传递:


function makeRequest(method, path, options) {
  return fetch(method, path, options).catch(function(err) {
    Sentry.withScope(function(scope) {
      // group errors together based on their request and response
      scope.setFingerprint([method, path, String(err.statusCode)]);
      Sentry.captureException(err);
    });
  });
}


您可以使用变量替换将动态值填充到通常在服务器上计算出的指纹中。例如,可以添加值 {{default}},以将整个正常生成的分组哈希添加到指纹中。这些值与服务器端指纹识别相同。有关更多信息,请参见 Variables。


Group Errors With Greater Granularity


您的应用程序查询远程过程调用模型(Remote Procedure Call Model, RPC)接口或外部应用程序编程接口(external application Programming interface, API)服务,因此堆栈跟踪通常是相同的(即使传出请求非常不同)。


以下示例将进一步分解 Sentry 将创建的默认组(用 {{default}} 表示),并考虑错误对象的一些属性:


class MyRPCError extends Error {
  constructor(message, functionName, errorCode) {
    super(message);
    // The name of the RPC function that was called (e.g. "getAllBlogArticles")
    this.functionName = functionName;
    // For example a HTTP status code returned by the server.
    this.errorCode = errorCode;
  }
}
Sentry.init({
  ...,
  beforeSend: function(event, hint) {
    const exception = hint.originalException;
    if (exception instanceof MyRPCError) {
      event.fingerprint = [
        '{{ default }}',
        String(exception.functionName),
        String(exception.errorCode)
      ];
    }
    return event;
  }
});


Group Errors More Aggressively


通用错误(例如数据库连接错误)具有许多不同的堆栈跟踪,并且从不在一起。

以下示例将通过从数组中省略 {{ default }} 来完全覆盖 Sentry 的分组:


class DatabaseConnectionError extends Error {}
Sentry.init({
  ...,
  beforeSend: function(event, hint) {
    const exception = hint.originalException;
    if (exception instanceof DatabaseConnectionError) {
      event.fingerprint = ['database-connection-error'];
    }
    return event;
  }
});


Fingerprint Rules



Fingerprint 规则(以前称为服务器端指纹)也配置了类似于 stack trace rules 的配置,但语法略有不同。匹配器(matchers)是相同的,但不是翻转标志(flipping flags),而是分配一个指纹,它完全覆盖默认分组。


这些规则可以在 Settings > Projects > [project] > Issue Grouping > Fingerprint Rules 中按项目设置。Group Settings 有输入字段,您可以在其中写入自定义指纹规则。该语法遵循 Discover queries 中的语法。如果要否定匹配,可以在表达式前面加上感叹号(!)。


所有值都匹配,并且在堆栈跟踪的情况下,将考虑所有帧。如果所有匹配项都匹配,则应用指纹。

Fingerprinting Config


# You can use comments to explain the rules.  Rules themselves follow the
# following syntax:
matcher:expression -> list of values
# The list of values can be hardcoded or substituted values.


下面是一个实际的示例,它将特定类型的异常组合在一起:


error.type:DatabaseUnavailable -> system-down
error.type:ConnectionError -> system-down
error.value:"connection error: *" -> connection-error, {{ transaction }}


Matchers


匹配器通常使用通配符语法。可以使用以下匹配器:

error.type

  • alias: type
  • 与异常类型(异常名称)匹配。匹配以区分大小写的形式进行。


error.type:ZeroDivisionError -> zero-division
error.type:ConnectionError -> connection-error


error.value

  • alias: value
  • 与异常值匹配。错误或异常通常具有易于理解的描述(值)。该匹配器允许不区分大小写的匹配。


error.value:"connection error (code: *)" -> connection-error
error.value:"could not connect (*)" -> connection-error


message

  • 匹配日志消息。它还会自动检查其他异常值,因为它们很难分开。匹配不区分大小写。


message:"system encountered a fatal problem: *" -> fatal-log


logger

  • 匹配 logger 的名称,这对于将 logger 的所有消息组合在一起非常有用。此匹配区分大小写。


logger:"com.myapp.mypackage.*" -> mypackage-logger


level

  • 在日志级别匹配。匹配不区分大小写。


logger:"com.myapp.FooLogger" level:"error" -> mylogger-error


tags.tag_name

  • 与标签 tag_name 的值匹配。这对于过滤某些类型的事件很有用。例如,您可以分离由特定服务器引起的事件:


tags.server_name:"canary-*.mycompany.internal" -> canary-events


stack.abs_path

  • alias: path
  • 在事件的路径上匹配,并且不区分大小写。它使用路径遍历语义,这意味着 * 不匹配斜杠,而 ** 匹配。请注意,此匹配器在 abs_pathfilename 上都匹配,因为 SDK 关于如何支持这些值可能会非常不一致。如果 glob 匹配这些值中的任何一个,则视为匹配。


stack.abs_path:"**/my-utils/*.js" -> my-utils, {{ error.type }}


stack.module

  • alias: module
  • stack.abs_path 类似,但是匹配模块名称。匹配区分大小写,并且会应用常规的规则(* 也匹配斜杠)。


stack.module:"*/my-utils/*" -> my-utils, {{ error.type }}


stack.function

  • alias: function
  • 检查堆栈跟踪中的任何函数是否与全局匹配。匹配区分大小写:


stack.function:"my_assertion_failed" -> my-assertion-failed


stack.package

  • alias: package
  • 与 frame 的 "package" 匹配。这通常是包含 frame 的 debug symbol/object file 的名称。如果有任何 frame 与该目标文件匹配,那么它将匹配。


stack.package:"**/libcurl.dylib" -> libcurl
stack.package:"**/libcurl.so" -> libcurl


family

  • 用于 "scope" 匹配器。存在以下族:用于任何类型的 JavaScript 事件的 javascript,用于任何类型的 Native 事件的 native。任何其他平台称为 other


family:native !stack.module:"myproject::*" -> not-from-my-project


app

  • 检查 frame 是否在应用程序内。与其他匹配器结合使用时特别有用。可能的值为 yesno


app:yes stack.function:"assert" -> assert


Combining Matchers


当多个匹配器组合在一起时,它们都需要匹配。在 frame 上运行的匹配器必须全部应用于同一 frame;否则,它们不被视为匹配项。


例如,如果在函数名称和模块名称上都匹配,则仅当 frame 同时在函数名称和模块名称上匹配时,才存在匹配项。一个frame 仅与函数名称匹配是不够的,即使另一个 frame 本身会与模块名称匹配也是如此。


# this matches if a frame exists with a specific function and module name
# and also a specific error type is thrown
error.type:ConnectionError stack.function:"connect" stack.module:"bot" -> bot-error


Variables


在 fingerprint 的右边,你可以使用常数值和变量。变量会被自动替换,并具有与匹配器相同的名称,但它们的填充方式可能不同。


变量用双花括号括起来({{variable_name}})。

{{ default }}

  • 这将填充正常分组操作将产生的默认 fingerprint。如果您想用其他方法细分一个已经存在的组,这将非常有用:


stack.function:"query_database" -> {{ default }}, {{ transaction }}


{{ transaction }}

  • 这会将 transaction 名称填写到 transaction 中。它将强制为每个 transaction 创建一个组:


error.type:"ApiError" -> api-error, {{ transaction }}


{{ error.type }}

  • alias: {{ type }}
  • 这将填写发生的错误的名称。使用 ·chained exceptions· 时,它将是最近抛出的错误。这将强制每个 ·transaction· 创建一个组:


stack.function:"evaluate_script" -> script-evaluation, {{ error.type }}


{{ stack.function }}

  • alias: {{ function }}
  • 这将填充 "crashing frame," 的功能名称,也称为应用程序代码的最上层 frame。


error.type:"ScriptError" -> script-evaluation, {{ stack.function }}


{{ stack.module }}

  • alias: {{ module }}
  • 这将填写"crashing frame,"的模块名称,也称为应用程序代码的最上层 frame。


error.type:"ScriptError" -> script-evaluation, {{ stack.module }}


{{ stack.package }}

  • alias: {{ package }}
  • 这将填写 "crashing frame," 的 package 名称(object file),也称为应用程序代码的最上层 frame。


stack.function:"assert" -> assertion, {{ stack.package }}


{{ logger }}

  • 这将填写引起事件的 logger 的名称。


message:"critical connection error*" -> connection-error, {{ logger }}


{{ level }}

  • 这将填充用于创建事件的日志级别的名称。


message:"connection error*" -> connection-error, {{ logger }}, {{ level }}


{{ tags.tag_name }}

  • 这会将 tag 的值填充到 fingerprint 中,例如,可以使用 fingerprint 按 server name 或类似名称拆分事件。


message:"connection error*" -> connection-error, {{ tags.server_name }}


Stack Trace Rules



如果使用堆栈跟踪进行分组,则堆栈跟踪规则(以前称为分组增强)会影响输入该算法的数据。可以在 Settings > Projects > [project] > Issue Grouping > Stack Trace Rules 下,针对每个项目配置这些规则。


每行都是一条规则;当所有表达式匹配时,一个或多个匹配表达式后跟一个或多个要执行的动作。所有规则在堆栈跟踪中的所有帧上从上到下执行。

堆栈跟踪规则的语法类似于:


matcher-name:expression other-matcher:expression ... action1 action2 ...


该语法遵循 Discover queries 中的语法。如果要否定匹配,可以在表达式前面加上感叹号(!)。

下面是一个实际的例子:


# mark all code in node modules not to be in app
stack.abs_path:**/node_modules/**         -app
# remove all generated javascript code from all grouping
stack.abs_path:**/generated/**.js         -group


Matchers


可以在一行中定义多个匹配器。下面的匹配器是可用的:

family

  • 匹配通用 platform family,目前包括 javascript, native 和 other。逗号分隔规则将它们应用于多个平台。


family:javascript stack.abs_path:**/generated/**  -group


stack.abs_path

  • alias: path
  • 该匹配器对堆栈跟踪中路径上的 Unix glob 行为不区分大小写。路径分隔符被标准化为 /。作为特殊规则,如果文件名是相对的,则它仍在 **/ 上匹配。


# match on all files under `project` with a `.c` extension
stack.abs_path:**/project/**.c` +app
# matches on vendor/foo without sub folders
stack.abs_path:**/vendor/foo/*.c` -app
# matches on `foo.c` as well as `foo/bar.c`.
stack.abs_path:**/*.gen.c` -group


stack.module

  • alias: module
  • Module 与 path 类似,但与 module 匹配。它不用于 Native,但用于 JavaScript、Python 和类似平台。匹配是区分大小写的,常规通配符是可用的。请注意,modules 不是 packages,这可能会让 Native 环境感到困惑。

stack.function

  • alias: function
  • 匹配堆栈跟踪中的函数,并且使用常规通配符区分大小写。


stack.function:myproject_* +app
stack.function:malloc      -group


stack.package

  • alias: package
  • 在堆栈跟踪中匹配 package。package 是包含 functionmodule 的容器。这是一个 .jar ,一个 .dylib 或类似的。匹配规则与 path 相同。例如,这通常是一个绝对路径。


stack.package:**/libcurl.dylib -group


app

  • stack trace frame 的应用内标记的当前状态匹配。yes 表示该 frame 是应用程序内 frame,no 表示不是。


Actions


有两种类型的 actions:标记(flag)和变量(variables)设置。

flag 标识在所有匹配器都匹配并使用以下前缀时采取的动作:


  • + 设置 flag
  • - 取消设置 flag
  • ^ 适用于匹配帧之上的帧(走向崩溃)。
  • v 适用于匹配帧下面的帧(远离崩溃)。

例如,-group ^-group 从组中移除匹配帧和它上面的所有帧。

  • app:在应用程序内标记或取消标记 frame
  • group:从分组中添加或删除 frame

variables:可以设置变量(variable=value)。当前只有一种:

  • max-frames:设置要分组的总帧数。默认值为 0,表示“所有帧”。如果设置为 3,则仅考虑前三个帧。

如果一行以 hash(#) 作为前缀,则它是一个注释并被忽略。


stack.abs_path:**/node_modules/** -group
stack.abs_path:**/app/utils/requestError.jsx -group
stack.abs_path:**src/getsentry/src/getsentry/** +app
family:native max-frames=3
stack.function:fetchSavedSearches v-group
stack.abs_path:**/app/views/**.jsx stack.function:fetchData ^-group
family:native stack.function:SpawnThread v-app -app
family:native stack.function:_NSRaiseError ^-group -app
family:native stack.function:std::* -app
family:native stack.function:core::* -app


Recommendations


这些建议将大大改善您的即用型分组体验。

Mark in-app Frames

为了主动改善您的体验,请帮助 Sentry 确定堆栈跟踪中的哪些帧是“应用程序内”(属于您自己的应用程序),哪些不是。SDK 定义了默认规则,但是在许多情况下,也可以在服务器上进行改进。特别是对于需要服务器端处理的语言(例如,Native C,C++ 或 JavaScript),最好在服务器上覆盖它。


stack.function:myapplication::* +app


你也可以通过标记其他帧 “not in-app” 来达到同样的效果。然而,如果是这种情况,你应该确保首先将所有帧设置为 “in-app”,以覆盖默认值:


app:no                   +app
stack.function:std::*    -app
stack.function:boost::*  -app


你需要强制所有帧首先在应用程序内,因为客户端 SDK 或早期处理可能已经设置了一些默认值。


Cut Stack Traces


在许多情况下,您要删除堆栈跟踪的顶部或底部。例如,许多代码库使用通用函数来生成错误。在这种情况下,错误机制将显示为堆栈跟踪的一部分。

例如,如果你使用 Rust,你可能想要删除一些与 panic 处理相关的 frames:


stack.function:std::panicking::begin_panic       ^-app -app ^-group
stack.function:core::panicking::begin_panic      ^-app -app ^-group


在这里,我们告诉系统从 begin-panic 到崩溃位置的所有 frame 都不是应用程序的一部分(包括 panic frame 本身)。在所有情况下,以上所有 frame 均与分组无关。

同样,您也可以删除堆栈跟踪的 base。如果您有不同的主循环来驱动应用程序,则此功能特别有用:


例如,如果你使用 Rust,你可能想要删除一些与 panic 处理相关的 frames:


stack.function:std::panicking::begin_panic       ^-app -app ^-group
stack.function:core::panicking::begin_panic      ^-app -app ^-group


这并不适用于所有的项目,但它可以很好地工作于许多崩溃的大型应用程序。默认的策略是考虑与分组相关的大多数堆栈跟踪。这意味着导致崩溃的每个不同的堆栈跟踪都将导致创建不同的组。如果你不想这样,你可以通过限制应该考虑的帧数来强制设置更大的组。


例如,如果堆栈跟踪中的任何帧都指向一个公共的外部库,你可以告诉系统只考虑 top N 帧:


# always only consider the top 1 frame for all native events
family:native max-frames=1
# if the bug is in proprietarymodule.so, only consider top 2 frames
family:native stack.package:**/proprietarymodule.so  max-frames=2
# these are functions we want to consider much more of the stack trace for
family:native stack.function:KnownBadFunction1  max-frames=5
family:native stack.function:KnownBadFunction2  max-frames=5


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
5天前
|
存储 Kubernetes 调度
|
6天前
|
弹性计算 Kubernetes Cloud Native
云原生架构下的微服务设计原则与实践####
本文深入探讨了在云原生环境中,微服务架构的设计原则、关键技术及实践案例。通过剖析传统单体架构面临的挑战,引出微服务作为解决方案的优势,并详细阐述了微服务设计的几大核心原则:单一职责、独立部署、弹性伸缩和服务自治。文章还介绍了容器化技术、Kubernetes等云原生工具如何助力微服务的高效实施,并通过一个实际项目案例,展示了从服务拆分到持续集成/持续部署(CI/CD)流程的完整实现路径,为读者提供了宝贵的实践经验和启发。 ####
|
4天前
|
JavaScript 持续交付 Docker
解锁新技能:Docker容器化部署在微服务架构中的应用
【10月更文挑战第29天】在数字化转型中,微服务架构因灵活性和可扩展性成为企业首选。Docker容器化技术为微服务的部署和管理带来革命性变化。本文探讨Docker在微服务架构中的应用,包括隔离性、可移植性、扩展性、版本控制等方面,并提供代码示例。
29 1
|
7天前
|
Kubernetes Cloud Native API
云原生架构下微服务治理的深度探索与实践####
本文旨在深入剖析云原生环境下微服务治理的核心要素与最佳实践,通过实际案例分析,揭示高效、稳定的微服务架构设计原则及实施策略。在快速迭代的云计算领域,微服务架构以其高度解耦、灵活扩展的特性成为众多企业的首选。然而,伴随而来的服务间通信、故障隔离、配置管理等挑战亦不容忽视。本研究聚焦于云原生技术栈如何赋能微服务治理,涵盖容器编排(如Kubernetes)、服务网格(如Istio/Envoy)、API网关、分布式追踪系统等关键技术组件的应用与优化,为读者提供一套系统性的解决方案框架,助力企业在云端构建更加健壮、可维护的服务生态。 ####
|
7天前
|
监控 安全 Cloud Native
云原生安全:Istio在微服务架构中的安全策略与实践
【10月更文挑战第26天】随着云计算的发展,云原生架构成为企业数字化转型的关键。微服务作为其核心组件,虽具备灵活性和可扩展性,但也带来安全挑战。Istio作为开源服务网格,通过双向TLS加密、细粒度访问控制和强大的审计监控功能,有效保障微服务间的通信安全,成为云原生安全的重要工具。
25 2
|
8天前
|
Kubernetes 关系型数据库 MySQL
Kubernetes入门:搭建高可用微服务架构
【10月更文挑战第25天】在快速发展的云计算时代,微服务架构因其灵活性和可扩展性备受青睐。本文通过一个案例分析,展示了如何使用Kubernetes将传统Java Web应用迁移到Kubernetes平台并改造成微服务架构。通过定义Kubernetes服务、创建MySQL的Deployment/RC、改造Web应用以及部署Web应用,最终实现了高可用的微服务架构。Kubernetes不仅提供了服务发现和负载均衡的能力,还通过各种资源管理工具,提升了系统的可扩展性和容错性。
29 3
|
12天前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【10月更文挑战第22天】随着云计算和容器技术的快速发展,微服务架构逐渐成为现代企业级应用的首选架构。微服务架构将一个大型应用程序拆分为多个小型、独立的服务,每个服务负责完成一个特定的功能。这种架构具有灵活性、可扩展性和易于维护的特点。在构建微服务架构时,Docker和Kubernetes是两个不可或缺的工具,它们可以完美搭档,为微服务架构提供高效的支持。本文将从三个方面探讨Docker和Kubernetes在构建高效微服务架构中的应用:一是Docker和Kubernetes的基本概念;二是它们在微服务架构中的作用;三是通过实例讲解如何使用Docker和Kubernetes构建微服务架构。
48 6
|
7天前
|
弹性计算 监控 Cloud Native
云原生架构下的性能优化实践与策略####
在数字化转型加速的今天,云原生技术以其弹性、敏捷和高效的特点成为企业IT架构转型的首选。本文深入探讨了云原生架构的核心理念,通过具体案例分析,揭示了性能优化的关键路径与策略,为开发者和企业提供了可操作的实践指南。 ####
|
11天前
|
监控 Cloud Native 测试技术
云原生架构下的性能优化与实践####
【10月更文挑战第21天】 本文深入探讨了在云原生环境下,如何通过一系列技术手段和最佳实践来提升应用性能。文章首先概述了云原生架构的基本原则与优势,随后详细分析了影响性能的关键因素,包括容器编排、微服务设计、持续集成/持续部署(CI/CD)流程以及监控与日志管理。针对这些因素,文中不仅介绍了具体的优化策略,如资源请求与限制的合理配置、服务间通信的高效实现、自动化测试与部署的优化,还结合案例分析,展示了如何在实际项目中有效实施这些策略以显著提升系统响应速度和处理能力。此外,文章还强调了性能测试的重要性,并提供了几种常用的性能测试工具和方法。最后,总结了云原生性能优化的未来趋势,为开发者和架构师
11 2
|
12天前
|
Kubernetes Cloud Native 持续交付
云原生架构下的微服务设计原则与最佳实践##
在数字化转型的浪潮中,云原生技术以其高效、灵活和可扩展的特性成为企业IT架构转型的首选。本文深入探讨了云原生架构的核心理念,聚焦于微服务设计的关键原则与实施策略,旨在为开发者提供一套系统性的方法论,以应对复杂多变的业务需求和技术挑战。通过分析真实案例,揭示了如何有效利用容器化、持续集成/持续部署(CI/CD)、服务网格等关键技术,构建高性能、易维护的云原生应用。文章还强调了文化与组织变革在云原生转型过程中的重要性,为企业顺利过渡到云原生时代提供了宝贵的见解。 ##