ITPub博客

首页 > 数据库 > 国内数据库 > 数据监控入门必读 - 在 NodeJS 中使用 OpenTelemetry 进行数据埋点指南

数据监控入门必读 - 在 NodeJS 中使用 OpenTelemetry 进行数据埋点指南

原创 国内数据库 作者:Greptime格睿科技 时间:2024-10-29 14:55:40 0 删除 编辑

在使用  OpenTelemetry  监控应用程序时,最基础的一步是进行 "OTel 数据埋点"。所谓的数据埋点,指的是为应用程序设置一些信号(如追踪、日志、指标等),这样你就可以对它的行为进行监控和分析。通过这些信号,你可以观察应用程序的运行状态和性能表现。

数据埋点概览

获取被监控的可观测数据的重要前提是正确的数据埋点,本文将介绍 OpenTelemetry 数据埋点的两种方式。想要了解 OpenTelemetry 的各个组成部分以及它们之间如何协同工作,请 参考这篇文章《云原生运维入门必看!OpenTelemetry 三大数据类型及核心组件解析》。

OpenTelemetry 的数据收集和跟踪功能(即 "检测" 或 "仪表化")是通过 OpenTelemetry API 来完成的。而 OpenTelemetry NodeJS SDK 实现了这个 API,提供了在 Node.js 应用中使用 OpenTelemetry 功能的方式。

这些组件可以无缝嵌入代码中,并生成所需的信号,以帮助用户全面掌握服务的运行状态。

OpenTelemetry 的设计注重模块化和灵活性,遵循单一职责原则。尽管涉及的术语较多,但主要的核心组件包括以下几个:

  1. 通过  Meter 或  Tracer 生成数据;

  2. 使用  Reader  或  Processor  对数据进行采样、过滤和转换;

  3. 通过  Exporter  或  Collector  将 OTLP 数据打包并传输到用户选择的与 OpenTelemetry 兼容的后端。

这个概述能帮助用户理解如何为应用程序进行埋点(即设置监控和收集数据的信号)。通过了解数据在不同组件之间是如何流动的,就能更好地为自己的应用程序进行仪表化设置,有效地监控和分析应用程序的性能和运行状态。

OpenTelemetry 可观测数据流向

OpenTelemetry 的设计优势在于允许用户根据 OTel API 的规范,自定义数据处理管道的各个部分。默认的实现方式能够以一致的格式生成指标和跨度(spans),并将这些数据包装成 OpenTelemetry 协议(OTLP)的格式,以便于 OTLP 后端系统进行接收和处理。

下图展示了数据如何在各组件间传输:

图片

(图 1:数据在组件中传输流程图)

这些标准操作流程为可观察性工具提供了标准的指导框架,使得用户能够选择符合该标准的多种工具。更多详细信息,请参阅 OpenTelemetry 规范。

在深入了解 OTel API 的作用及数据流向后,接下来我们来看看如何实际为应用程序进行埋点。埋点主要分为两类: 自动植入和手动植入,下节将讨论它们之间的区别及各自适用的场景。

自动植入埋点

自动植入是使用 OpenTelemetry 的最简单方式。该过程通过接入应用程序和服务的常见接口边缘,自动捕获一些最常见的协议操作信号。只需导入一个库并实例化一个单例,或者在某些框架和语言中,仅需安装 SDK 并导出一些环境变量即可。

以下是自动植入可以捕获的常见指标示例:

  • HTTP 请求
    • 请求持续时间
    • 响应状态码
    • URL 路径
    • HTTP 方法
  • 数据库查询

    • 查询执行时间
    • SQL 语句(已清理)
    • 数据库类型(如 MySQL、PostgreSQL)
  • 消息系统

    • 消息发布/消费操作
    • 队列名称
    • 消息大小
  • 框架特定信号

    • 针对 Web 框架(如 Express.js、Flask):路由处理、 中间件执行
    • 针对  ORM (如 Sequelize、SQLAlchemy):模型操作(创建、读取、更新、删除)
  • 运行时指标

    • CPU 使用率
    • 内存分配
    • 垃圾回收统计

为应用进行自动植入非常简单,以下是一个集成了 OpenTelemetry NodeJS SDK 的 Express 应用示例:


const express = 
require(
'express');

const { UserService } =  require( './services/userService')

// ---------------------------------------------------
// ---------------------------------------------------
// ---------------------------------------------------
// Import the OpenTelemetry SDK
const { NodeSDK } =  require( '@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } =  require( '@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } =  require( '@opentelemetry/exporter-trace-otlp-http');

// Initialize the OpenTelemetry SDK
const sdk =  new NodeSDK({
   traceExporter:  new OTLPTraceExporter(),
   instrumentations: [getNodeAutoInstrumentations()] 
  // sets up basic defaults for express http collection and app resource consumption
});

// Start the SDK
sdk.start();

// That's all the configuration needed to start collecting metrics
// ---------------------------------------------------
// ---------------------------------------------------
// ---------------------------------------------------

// Create and set up your Express app as usual
const app = express();

// Your routes and middleware here
app.get( '/', (req, res) => {
  res.send( 'Hello, OpenTelemetry!');
});

app.listen(...);

通过自动植入埋点收集信号,用户可以在代码改动极少的条件下获取大量可观察性数据,帮助快速启动 OpenTelemetry。虽然自动埋点已经可以提供非常高的价值,但在某些情况下,应用程序所有者可能需要监听应用程序中发生的更多自定义信号。开发者可以通过 手动植入实现对采集信号的精细控制。

手动植入埋点

手动植入的核心配置在于  provider,它作为用于创建输出信号对象的生成器。在这些生成器中,用户可以配置如下对象:

  • resource:标识生成遥测数据的实体。通常包括服务名称、主机信息、容器或 Pod 标识符、云提供商详细信息或描述遥测来源的其他元数据, resource 提供了数据来源的上下文信息。

  • meter / tracer:(如 ObservableGauge):实际捕获指标和 Trace 的工具。这些对象将用于生成遥测数据。

  • reader:(如 PeriodicExportingMetricReader):可以用于每 n 秒导出一次指标。

  • sampler: (如 TraceIdRatioBasedSampler):可用于捕获 r% 的请求。

  • exporter:(如 OTLPTraceExporter):用于将数据发送到 OTLP 兼容后端,如 GreptimeCloud。

以下示例展示了如何通过手动植入从 Tesla API 收集电池电量数据,并将指标发送到 GreptimeCloud 托管的 OTLP 后端:


const { MeterProvider } = 
require(
'@opentelemetry/sdk-metrics');

const { Resource } =  require( '@opentelemetry/resources');
const { SemanticResourceAttributes } =  require( '@opentelemetry/semantic-conventions');
const { NodeTracerProvider } =  require( '@opentelemetry/sdk-trace-node');
const { SimpleSpanProcessor, BatchSpanProcessor, ConsoleSpanExporter } =  require( '@opentelemetry/sdk-trace-base');
const { trace, metrics, context } =  require( '@opentelemetry/api');
const { OTLPMetricExporter } =  require( '@opentelemetry/exporter-metrics-otlp-http');
const { PeriodicExportingMetricReader } =  require( '@opentelemetry/sdk-metrics');
const teslajs =  require( 'teslajs');
const options = {
   authToken:  'your-access-token',
   vehicleID:  'your-vehicle-id'
};
// Configure the resource naming the given service
const resource =  new Resource({
  [SemanticResourceAttributes.SERVICE_NAME]:  'tesla-monitoring-app',
});

// Configure the exporter to be sent to Greptime cloud
const otlpExporter =  new OTLPMetricExporter({
   url:  'https://6qr5e68t5wpn.us-west-2.aws.greptime.cloud/v1/otlp/v1/metrics',
   headers: {
     'Authorization':  'Basic WxN5prHHwx1ATXMvduBlgy4K:xxxxxxx',
     'X-Greptime-DB-Name':  'my-greptime-cloud-instance@tesla-monitoring',
  },
});

// Set this MeterProvider to be global to the app being instrumented.
const meterProvider =  new MeterProvider({ resource });
opentelemetry.metrics.setGlobalMeterProvider(meterProvider);
const metricReader =  new PeriodicExportingMetricReader({
   exporter: otlpExporter,
   exportIntervalMillis:   exportIntervalMillis:  5 *  60 *  1000
});

meterProvider.addMetricReader(metricReader);

// Create and register the tracer
const tracerProvider =  new NodeTracerProvider();

// Configure span processor to send spans to simply log the results
tracerProvider.addSpanProcessor( new BatchSpanProcessor( new ConsoleSpanExporter()));
tracerProvider.register();

const tracer = trace.getTracer( 'example-basic-tracer-node');

const teslaMeter = metrics.getMeter(
   "tesla-instrumentation",
   '1.0',
);

const batteryGauge = teslaMeter.createObservableGauge( "tesla.battery");

async  function  pollTeslaData( ) {
   const span = tracer.startSpan( 'pollTeslaData');
   const ctx = trace.setSpan(context.active(), span);

   try {
     await context.with(ctx,  async () => {
       const vehicleData =  await teslajs.vehicleData()
vehicleData.charge_state.battery_level
      batteryGauge.addCallback( ( result) => {
        result.observe(batteryLevel);
      });
    });
  }  catch (error) {
    span.recordException(error);
  }  finally {
    span.end();
  }
}

// Poll Tesla data every 5 minutes
setInterval(pollTeslaData,  5 *  60 *  1000);

该示例展示了 OpenTelemetry 在捕获可观察性数据方面的广泛支持,并展示了如何快速启动。

分析埋点所捕获的数据

通过 GreptimeDB 的 Grafana 插件,你可以在 Grafana 中直接可视化从 OpenTelemetry 捕获的所有数据。几分钟内即可完成帐户设置,利用 OpenTelemetry 为你的服务提供新的见解。

(图 2:Grafana Dashboard 监控数据展示)

在后续文章中,我们将介绍如何将这些 OpenTelemetry 数据连接到 Grafana 进行可视化。如果你正在寻找性能卓越、可靠且开源的 OpenTelemetry 后端,欢迎了解 GreptimeDB。

❝

关于 Greptime

Greptime 格睿科技专注于为可观测、物联网及车联网等领域提供实时、高效的数据存储和分析服务,帮助客户挖掘数据的深层价值。目前基于云原生的时序数据库 GreptimeDB 已经衍生出多款适合不同用户的解决方案,更多信息或 demo 展示请联系下方小助手( 微信号:greptime)。

欢迎对开源感兴趣的朋友们参与贡献和讨论,从带有  good first issue 标签的 issue 开始你的开源之旅吧~期待在开源社群里遇见你!添加小助手微信即可加入“技术交流群”与志同道合的朋友们面对面交流哦~

Star us on GitHub Now:  https://github.com/GreptimeTeam/greptimedb
官网: https://greptime.cn/
文档: https://docs.greptime.cn/
Twitter:  https://twitter.com/Greptime
Slack:  https://greptime.com/slack
LinkedIn:  https://www.linkedin.com/company/greptime/

写留言
留言

    暂无留言


    来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70031880/viewspace-3043165/ ,如需转载,请注明出处,否则将追究法律责任。

    请登录后发表评论 登录
    全部评论
    Greptime 格睿科技致力于为智能汽车、物联网及可观测等产生大量时序数据的领域提供实时、高效的数据存储和分析服务,帮助客户挖掘数据的深层价值。

    注册时间:2023-07-13

    • 博文量
      63
    • 访问量
      61333