Sentry(v20.12.1) K8S 云原生架构探索,JavaScript 性能监控之管理 Transactions

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: Sentry(v20.12.1) K8S 云原生架构探索,JavaScript 性能监控之管理 Transactions

Automatic Instrumentation



要自动捕获 transactions,必须首先在应用程序中启用跟踪。

@sentry/tracing 包提供了一个 BrowserTracing 集成,以添加 automatic instrumentation 来监视浏览器应用程序的性能。


What Automatic Instrumentation Provides


BrowserTracing 集成为每个页面 load 和 navigation 事件创建一个新 transaction,并为在打开这些 transactions 时发生的每个 XMLHttpRequestfetch 请求创建一个 child span。进一步了解 traces, transactions, and spans。


Enable Automatic Instrumentation


要启用此自动跟踪,请在 SDK 配置选项中包含 BrowserTracing 集成。(请注意,使用 ESM 模块时,主要的 @sentry/* import 必须先于 @sentry/tracing import。)

配置完成后,在 sentry.io 中查看 transactions 时,您将同时看到 pageloadnavigation

ESM


// If you're using one of our integration packages, like `@sentry/react` or `@sentry/angular`,
// substitute its name for `@sentry/browser` here
import * as Sentry from "@sentry/browser";
import { Integrations as TracingIntegrations } from "@sentry/tracing"; // Must import second
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Integrations.BrowserTracing({
      tracingOrigins: ["localhost", "my-site-url.com", /^\//],
      // ... other options
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


CDN


Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Sentry.Integrations.BrowserTracing({
      tracingOrigins: ["localhost", "my-site-url.com", /^\//],
      // ... other options
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


Configuration Options


您可以将许多不同的选项传递给 BrowserTracing 集成(作为 {optionName: value} 形式的对象),但是它具有合理的默认值。有关所有可能的选项,请参见 TypeDocs。


tracingOrigins


tracingOrigins 的默认值是 ['localhost', /^\//]。JavaScript SDK 将 sentry-trace header 附加到其目标包含列表中的字符串或匹配列表中的正则表达式的所有传出的 XHR/fetch 请求。如果您的前端向另一个域发出请求,则需要在其中添加它,以将 sentry-trace header 传播到后端服务,这是将 transactions 链接在一起作为单个跟踪的一部分所必需的。tracingOrigins 选项与整个请求 URL 匹配,而不仅仅是域。使用更严格的正则表达式来匹配 URL 的某些部分,可以确保请求不用不必要地附加 sentry-trace header。


例如:

  • 前端应用程序是从 example.com 提供的
  • 后端服务由 api.example.com 提供
  • 前端应用程序对后端进行 API 调用
  • 因此,该选项需要这样配置:new Integrations.BrowserTracing({tracingOrigins: ['api.example.com']})
  • 现在,向 api.example.com 发出的 XHR/fetch 请求将获得附加的 sentry-trace header


Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Integrations.BrowserTracing({
      tracingOrigins: ["localhost", "my-site-url.com"],
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


您将需要配置您的 Web 服务器 CORS 以允许 sentry-trace header。该配置可能类似于 "Access-Control-Allow-Headers: sentry-trace",但是该配置取决于您的设置。如果您不允许使用 sentry-trace header,则该请求可能会被阻止。


beforeNavigate

对于 pageloadnavigation transactions,BrowserTracing 集成使用浏览器的 window.location API 生成 transaction 名称。要自定义 pageloadnavigation transactions 的名称,您可以向 BrowserTracing 集成提供 beforeNavigate 选项。该选项允许您修改 transaction 名称以使其更通用,例如,名为 GET /users/12312012GET /users/11212012 的 transactions 都可以重命名为 GET /users/:userid,以便他们可以在一起。


import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Integrations.BrowserTracing({
      beforeNavigate: context => {
        return {
          ...context,
          // You could use your UI's routing library to find the matching
          // route template here. We don't have one right now, so do some basic
          // parameter replacements.
          name: location.pathname
            .replace(/\d+/g, "<digits>")
            .replace(/[a-f0-9]{32}/g, "<hash>"),
        };
      },
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


shouldCreateSpanForRequest

此函数可用于过滤掉不需要的 spans,例如 XHR 的运行状况检查或类似的检查。默认情况下,shouldCreateSpanForRequest 已经过滤掉了除了 tracingOrigins 中定义的内容以外的所有内容。


import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    new Integrations.BrowserTracing({
      shouldCreateSpanForRequest: url => {
        // Do not create spans for outgoing requests to a `/health/` endpoint
        return !url.match(/\/health\/?$/);
      },
    }),
  ],
  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});


Manual Instrumentation


要手动捕获 transactions,必须首先在应用程序中启用跟踪。

要手动 instrument 代码的某些区域,可以创建 transactions 来捕获它们。

这对于所有 JavaScript SDK(后端和前端)均有效,并且独立于 ExpressHttpBrowserTracing 集成而工作。


const transaction = Sentry.startTransaction({ name: "test-transaction" });
const span = transaction.startChild({ op: "functionX" }); // This function returns a Span
// functionCallX
span.finish(); // Remember that only finished spans will be sent with the transaction
transaction.finish(); // Finishing the transaction will send it to Sentry


例如,如果要为页面上的用户交互创建 transaction,请执行以下操作:


// Let's say this function is invoked when a user clicks on the checkout button of your shop
shopCheckout() {
  // This will create a new Transaction for you
  const transaction = Sentry.startTransaction('shopCheckout');
  // set the transaction on the scope so it picks up any errors
  hub.configureScope(scope => scope.setSpan(transaction));
  // Assume this function makes an xhr/fetch call
  const result = validateShoppingCartOnServer();
  const span = transaction.startChild({
    data: {
      result
    },
    op: 'task',
    description: `processing shopping cart result`,
  });
  processAndValidateShoppingCart(result);
  span.finish();
  transaction.finish();
}


这个例子将发送一个 transaction shopCheckout 到 Sentry。交易将包含一个 task span,该 span 衡量 processAndValidateShoppingCart 花费了多长时间。最后,对 transaction.finish() 的调用将完成transaction 并将其发送给 Sentry。


在为异步操作创建 spans 时,您还可以利用 Promises。但是请记住,必须在调用 transaction.finish() 之前将其 span 包含在事务中。


例如:


function processItem(item, transaction) {
  const span = transaction.startChild({
    op: "http",
    description: `GET /items/:item-id`,
  });
  return new Promise((resolve, reject) => {
    http.get(`/items/${item.id}`, response => {
      response.on("data", () => {});
      response.on("end", () => {
        span.setTag("http.status_code", response.statusCode);
        span.setData("http.foobarsessionid", getFoobarSessionid(response));
        span.finish();
        resolve(response);
      });
    });
  });
}


Connect Backend and Frontend Transactions



要将后端和前端 transactions 连接到单个一致的跟踪中,Sentry 使用 trace_id 值,该值在前端和后端之间传播。根据情况,此 ID 可以在请求 header 或 HTML <meta> 标记中传输。以这种方式链接 transactions 使您可以在 Sentry UI 中在它们之间进行导航,因此您可以更好地了解系统的不同部分如何相互影响。您可以在我们的分布式跟踪文档中了解有关此模型的更多信息。


Pageload


在前端和后端都启用跟踪并利用自动前端 instrumentation 功能时,可以将前端上自动生成的 pageload transaction 与后端上的为页面服务提供请求的 transaction 相连接。因为在浏览器中运行的 JavaScript 代码无法读取当前页面的响应 headers,所以 trace_id 必须在响应本身中传输,尤其是在从后端发送的 HTML <head> 中的 <meta> 标签中。


<html>
  <head>
    <meta name="sentry-trace" content="{{ span.toTraceparent() }}" />
    <!-- ... -->
  </head>
</html>


name 属性必须是字符串 "sentry-trace"content 属性必须由后端的 Sentry SDK 使用 span.toTraceparent()(或等效项,取决于后端平台)生成。这保证了将为每个请求生成一个新的唯一值。


span 引用是为 HTML 提供服务的 transaction,或其任何 child spans。它定义了 pageload transaction 的父级。


一旦数据被包含在 <meta> 标签中,我们的 BrowserTracing 集成将自动获取数据并将其链接到在 pageload 时生成的 transaction。(请注意,它不会链接到自动生成的 navigation transactions,即不需要重新加载整个页面的 transaction。每个 transaction 都是后端不同请求 transaction 的结果,因此应具有唯一的 trace_id。)


Navigation and Other XHR Requests


加载页面后,它发出的任何请求(以及后端产生的任何请求)都通过请求 header 链接。

就像上面讨论的 <meta> 标签一样,标题的名称是 sentry-trace,其值是通过调用 span.toTraceparent()(或等效的)来获得的,其中 span 是相关 transaction 或其任何子项。


Sentry 的所有与跟踪相关的集成(BrowserTracingHttpExpress)都会针对它们生成的所有 transactions 和 spans 自动生成或拾取并传播此 header。在手动创建 transaction 或 span 的任何情况下,您都可以自己附加和读取 header,这样做很有意义。


Control Data Truncation


当前,每个标签的最大字符数限制为200个字符。超过200个字符限制的标签将被截断,丢失潜在的重要信息。要保留此数据,您可以将数据拆分为多个标签。

例如,一个200多个字符标记的请求:


https://empowerplant.io/api/0/projects/ep/setup_form/?user_id=314159265358979323846264338327&tracking_id=EasyAsABC123OrSimpleAsDoReMi&product_name=PlantToHumanTranslator&product_id=161803398874989484820458683436563811772030917980576


上面200个字符以上的请求将被截断为:


https://empowerplant.io/api/0/projects/ep/setup_form/?user_id=314159265358979323846264338327&tracking_id=EasyAsABC123OrSimpleAsDoReMi&product_name=PlantToHumanTranslator&product_id=1618033988749894848


相反,使用 span.set_tagspan.set_data 会使用结构化元数据保留此查询的详细信息。这可以通过 baseUrlendpointparameters 完成:


const baseUrl = "https://empowerplant.io";
const endpoint = "/api/0/projects/ep/setup_form";
const parameters = {
  user_id: 314159265358979323846264338327,
  tracking_id: "EasyAsABC123OrSimpleAsDoReMi",
  product_name: PlantToHumanTranslator,
  product_id: 161803398874989484820458683436563811772030917980576,
};
const span = transaction.startChild({
  op: "request",
  description: "setup form",
});
span.setTag("baseUrl", baseUrl);
span.setTag("endpoint", endpoint);
span.setData("parameters", parameters);
// you may also find some parameters to be valuable as tags
span.setData("user_id", parameters.user_id);
http.get(`${base_url}/${endpoint}/`, (data = parameters));


Group Transactions


Sentry 捕获 transactions 时,将为它们分配一个 transaction 名称。该名称通常由 Sentry SDK 根据您使用的框架集成自动生成。如果您无法利用自动 transaction 生成(或想要自定义 transaction 名称的生成方式),则可以使用,在使用配置初始化 SDK 时注册的全局事件处理器。


在 node.js 应用程序中执行此操作的示例:


import { addGlobalEventProcessor } from "@sentry/node";
addGlobalEventProcessor(event => {
  // if event is a transaction event
  if (event.type === "transaction") {
    event.transaction = sanitizeTransactionName(event.transaction);
  }
  return event;
});


对于使用 BrowserTracing 集成的浏览器 JavaScript 应用程序,beforeNavigate 选项可用于根据 URL 更好地将 navigation/pageload transactions 分组在一起。


import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
Sentry.init({
  // ...
  integrations: [
    new Integrations.BrowserTracing({
      beforeNavigate: context => {
        return {
          ...context,
          // You could use your UI's routing library to find the matching
          // route template here. We don't have one right now, so do some basic
          // parameter replacements.
          name: location.pathname
            .replace(/\d+/g, "<digits>")
            .replace(/[a-f0-9]{32}/g, "<hash>"),
        };
      },
    }),
  ],
});


Retrieve an Active Transaction


如果要将 Spans 附加到已在进行中的 transaction 中,例如在对 transaction 进行分组时,可以使用 Sentry.getCurrentHub().getScope().getTransaction()。当 scope 中有正在运行的 transaction 时,此函数将返回一个 Transaction 对象,否则它将返回 undefined。如果您使用的是 BrowserTracing 集成,则默认情况下,我们会将 transaction 附加到 Scope,因此您可以执行以下操作:


function myJsFunction() {
  const transaction = Sentry.getCurrentHub()
    .getScope()
    .getTransaction();
  if (transaction) {
    let span = transaction.startChild({
      op: "encode",
      description: "parseAvatarImages",
    });
    // Do something
    span.finish();
  }
}


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
8天前
|
边缘计算 Cloud Native 安全
构建灵活高效的下一代应用架构 随着企业数字化转型的加速,云原生技术正逐渐成为构建现代化应用程序的关键支柱。
随着企业数字化转型加速,云原生技术逐渐成为构建现代化应用的关键。本文探讨了云原生的核心概念(如容器化、微服务、DevOps)、主要应用场景(如金融、电商、IoT)及未来发展趋势(如无服务器计算、边缘计算、多云架构),并分析了面临的挑战,如架构复杂性和安全问题。云原生技术为企业提供了更灵活、高效的应用架构,助力数字化转型。
29 4
|
6天前
|
Kubernetes Cloud Native 持续交付
云端新纪元:云原生技术重塑IT架构####
【10月更文挑战第20天】 本文深入探讨了云原生技术的兴起背景、核心理念、关键技术组件以及它如何引领现代IT架构迈向更高效、灵活与可扩展的新阶段。通过剖析Kubernetes、微服务、Docker等核心技术,本文揭示了云原生架构如何优化资源利用、加速应用开发与部署流程,并促进企业数字化转型的深度实践。 ####
|
5天前
|
监控 Cloud Native Java
云原生架构下微服务治理策略与实践####
【10月更文挑战第20天】 本文深入探讨了云原生环境下微服务架构的治理策略,通过分析当前技术趋势与挑战,提出了一系列高效、可扩展的微服务治理最佳实践方案。不同于传统摘要概述内容要点,本部分直接聚焦于治理核心——如何在动态多变的分布式系统中实现服务的自动发现、配置管理、流量控制及故障恢复,旨在为开发者提供一套系统性的方法论,助力企业在云端构建更加健壮、灵活的应用程序。 ####
46 10
|
5天前
|
运维 Cloud Native 持续交付
云原生架构下的微服务设计原则与实践####
【10月更文挑战第20天】 本文深入探讨了云原生环境中微服务设计的几大核心原则,包括服务的细粒度划分、无状态性、独立部署、自动化管理及容错机制。通过分析这些原则背后的技术逻辑与业务价值,结合具体案例,展示了如何在现代云平台上实现高效、灵活且可扩展的微服务架构,以应对快速变化的市场需求和技术挑战。 ####
25 7
|
5天前
|
监控 Cloud Native 持续交付
云原生架构下微服务的最佳实践与挑战####
【10月更文挑战第20天】 本文深入探讨了云原生架构在现代软件开发中的应用,特别是针对微服务设计模式的最优实践与面临的主要挑战。通过分析容器化、持续集成/持续部署(CI/CD)、服务网格等关键技术,阐述了如何高效构建、部署及运维微服务系统。同时,文章也指出了在云原生转型过程中常见的难题,如服务间的复杂通信、安全性问题以及监控与可观测性的实现,为开发者和企业提供了宝贵的策略指导和解决方案建议。 ####
29 5
|
3天前
|
监控 Cloud Native 测试技术
云原生架构下的性能优化与实践####
【10月更文挑战第21天】 本文深入探讨了在云原生环境下,如何通过一系列技术手段和最佳实践来提升应用性能。文章首先概述了云原生架构的基本原则与优势,随后详细分析了影响性能的关键因素,包括容器编排、微服务设计、持续集成/持续部署(CI/CD)流程以及监控与日志管理。针对这些因素,文中不仅介绍了具体的优化策略,如资源请求与限制的合理配置、服务间通信的高效实现、自动化测试与部署的优化,还结合案例分析,展示了如何在实际项目中有效实施这些策略以显著提升系统响应速度和处理能力。此外,文章还强调了性能测试的重要性,并提供了几种常用的性能测试工具和方法。最后,总结了云原生性能优化的未来趋势,为开发者和架构师
10 2
|
4天前
|
Kubernetes Cloud Native 持续交付
云原生架构下的微服务设计原则与最佳实践##
在数字化转型的浪潮中,云原生技术以其高效、灵活和可扩展的特性成为企业IT架构转型的首选。本文深入探讨了云原生架构的核心理念,聚焦于微服务设计的关键原则与实施策略,旨在为开发者提供一套系统性的方法论,以应对复杂多变的业务需求和技术挑战。通过分析真实案例,揭示了如何有效利用容器化、持续集成/持续部署(CI/CD)、服务网格等关键技术,构建高性能、易维护的云原生应用。文章还强调了文化与组织变革在云原生转型过程中的重要性,为企业顺利过渡到云原生时代提供了宝贵的见解。 ##
|
4天前
|
运维 Cloud Native API
云原生时代下的微服务架构实践
【10月更文挑战第22天】在数字化转型的浪潮中,云原生技术正以前所未有的速度重塑软件开发和运维的模式。微服务架构作为云原生的重要组成部分,其设计哲学、技术栈选择以及与传统单体应用的根本区别成为了现代软件工程讨论的焦点。本文将深入探讨微服务架构的核心概念,通过实际案例分析其在云平台下的应用,并分享在实施过程中的经验教训,旨在为读者提供一套清晰的微服务架构实践指南。
|
9天前
|
运维 Cloud Native 持续交付
云原生技术在现代IT架构中的深度应用与挑战####
【10月更文挑战第17天】 本文深入剖析了云原生技术的精髓,探讨其在现代IT架构转型中的核心作用与面临的挑战。云原生不仅是一种技术实现,更是企业数字化转型的重要推手,通过容器化、微服务、持续集成/持续部署(CI/CD)等关键要素,重塑软件开发、部署与运维模式。文章首先概述了云原生的基本原则与核心组件,随后分析了其如何促进企业敏捷性、可扩展性和资源利用率的提升,同时也指出了在安全性、复杂性管理及人才技能匹配等方面存在的挑战,并提出了相应的对策建议。 ####
39 6
|
7天前
|
Cloud Native Devops 持续交付
云原生架构:重塑企业IT的无形之手####
本文旨在探讨云原生架构如何成为推动企业数字化转型的核心动力,它不仅是一种技术升级,更是业务与开发模式的深刻变革。通过剖析云原生的核心要素——微服务、容器化、持续集成/持续部署(CI/CD)、以及DevOps文化,本文揭示了这一架构如何提升系统的弹性、可扩展性和敏捷性,为企业在竞争激烈的市场环境中赋予快速响应和创新的能力。不同于传统综述,本文将以一个虚构案例贯穿始终,直观展示云原生架构从理论到实践的转化过程,为读者提供一幅生动的技术蓝图。 --- ###