HarmonyOS 鸿蒙Next中基于HiTraceChain实现分布式调用链跟踪

HarmonyOS 鸿蒙Next中基于HiTraceChain实现分布式调用链跟踪 如何基于HiTraceChain实现分布式调用链跟踪?

3 回复

使用场景

跨设备协同任务跟踪:在多设备协同的场景中,跟踪一个用户操作如何触发多个设备上的响应。

复杂业务流程故障定位:当应用出现异常(如支付失败、消息未送达)时,通过跟踪ID快速关联跨线程/进程的日志和事件,缩短问题定位时间。

异步任务监控:跟踪异步任务(如后台数据同步、消息推送)的执行流程和状态变化。

实现思路

第一步:使用hiTraceChain.begin()接口启动一个新的跟踪链,指定跟踪名称和标志。

第二步:跟踪标识(HiTraceId)会在业务流程中自动传递。对于跨进程/跨设备的调用,系统会确保跟踪标识的延续性。

第三步:在业务逻辑的关键节点(如方法调用、网络请求、数据库操作、UI响应等)使用hiTraceChain.tracepoint()接口记录埋点信息 。

第四步:业务流程结束后,调用hiTraceChain.end()接口结束跟踪链,释放相关资源 。

实现效果

完整实现代码

import { hilog, hiTraceChain } from '@kit.PerformanceAnalysisKit';
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct HiTraceChainDemo {
  @State traceLog: string = '';
  private traceId?: hiTraceChain.HiTraceId;
  private readonly DOMAIN: number = 0x0000;

  // 开始跟踪链
  startTraceChain() {
    try {
      // 开始一个新的跟踪链,指定跟踪名称和标志
      // INCLUDE_ASYNC: 跟踪同步和异步调用
      // TP_INFO: 在同步/异步调用的收发侧自动埋点,输出埋点信息和时间戳
      const flags = hiTraceChain.HiTraceFlag.INCLUDE_ASYNC | hiTraceChain.HiTraceFlag.TP_INFO;
      this.traceId = hiTraceChain.begin("DistributedTaskTrace", flags);

      this.traceLog += `[跟踪开始] chainId: ${this.traceId.chainId}\n`;
      hilog.info(this.DOMAIN, 'HiTraceChainDemo', 'Trace started. chainId: %{public}s', this.traceId.chainId.toString());

      promptAction.showToast({ message: '跟踪链已启动' });
    } catch (error) {
      const err = error as BusinessError;
      hilog.error(this.DOMAIN, 'HiTraceChainDemo', 'Failed to start trace. Code: %{public}d, Message: %{public}s', err.code, err.message);
      this.traceLog += `[启动失败] ${err.message}\n`;
    }
  }

  // 模拟业务流程:同步调用 + 异步调用 + 跨设备调用模拟
  async performBusinessFlow() {
    if (!this.traceId) {
      promptAction.showToast({ message: '请先启动跟踪链' });
      return;
    }

    this.traceLog += '\n=== 开始业务流程 ===\n';

    // 1. 同步调用埋点 (线程间通信)
    hiTraceChain.tracepoint(
      hiTraceChain.HiTraceCommunicationMode.THREAD,
      hiTraceChain.HiTraceTracepointType.CS,
      this.traceId,
      "开始同步数据处理"
    );

    // 模拟同步数据处理
    await this.simulateSyncProcessing();

    hiTraceChain.tracepoint(
      hiTraceChain.HiTraceCommunicationMode.THREAD,
      hiTraceChain.HiTraceTracepointType.CR,
      this.traceId,
      "同步数据处理完成"
    );

    this.traceLog += `[同步调用] 数据处理完成\n`;

    // 2. 异步调用埋点 (进程间通信模拟)
    hiTraceChain.tracepoint(
      hiTraceChain.HiTraceCommunicationMode.PROCESS,
      hiTraceChain.HiTraceTracepointType.CS,
      this.traceId,
      "发起异步网络请求"
    );

    // 模拟异步网络请求
    this.simulateAsyncNetworkRequest().then(() => {
      hiTraceChain.tracepoint(
        hiTraceChain.HiTraceCommunicationMode.PROCESS,
        hiTraceChain.HiTraceTracepointType.CR,
        this.traceId,
        "网络请求响应返回"
      );

      this.traceLog += `[异步调用] 网络请求完成\n`;
    });

    // 3. 跨设备调用埋点 (设备间通信模拟)
    hiTraceChain.tracepoint(
      hiTraceChain.HiTraceCommunicationMode.DEVICE,
      hiTraceChain.HiTraceTracepointType.CS,
      this.traceId,
      "发起跨设备协同请求"
    );

    // 模拟跨设备协同操作
    this.simulateCrossDeviceOperation().then(() => {
      hiTraceChain.tracepoint(
        hiTraceChain.HiTraceCommunicationMode.DEVICE,
        hiTraceChain.HiTraceTracepointType.CR,
        this.traceId,
        "跨设备协同操作完成"
      );

      this.traceLog += `[跨设备调用] 协同操作完成\n`;
    });

    this.traceLog += '=== 业务流程结束 ===\n\n';
  }

  // 模拟同步数据处理
  private async simulateSyncProcessing(): Promise<void> {
    return new Promise(resolve => {
      setTimeout(() => {
        hilog.info(this.DOMAIN, 'HiTraceChainDemo', 'Sync processing simulated');
        resolve();
      }, 500);
    });
  }

  // 模拟异步网络请求
  private async simulateAsyncNetworkRequest(): Promise<void> {
    return new Promise(resolve => {
      setTimeout(() => {
        hilog.info(this.DOMAIN, 'HiTraceChainDemo', 'Async network request simulated');
        resolve();
      }, 1000);
    });
  }

  // 模拟跨设备协同操作
  private async simulateCrossDeviceOperation(): Promise<void> {
    return new Promise(resolve => {
      setTimeout(() => {
        hilog.info(this.DOMAIN, 'HiTraceChainDemo', 'Cross-device operation simulated');
        resolve();
      }, 1500);
    });
  }

  // 结束跟踪链
  endTraceChain() {
    if (!this.traceId) {
      promptAction.showToast({ message: '无活跃跟踪链' });
      return;
    }

    try {
      hiTraceChain.end(this.traceId);
      this.traceLog += `[跟踪结束] chainId: ${this.traceId.chainId}\n`;
      hilog.info(this.DOMAIN, 'HiTraceChainDemo', 'Trace ended. chainId: %{public}s', this.traceId.chainId.toString());

      this.traceId = undefined;
      promptAction.showToast({ message: '跟踪链已结束' });
    } catch (error) {
      const err = error as BusinessError;
      hilog.error(this.DOMAIN, 'HiTraceChainDemo', 'Failed to end trace. Code: %{public}d, Message: %{public}s', err.code, err.message);
      this.traceLog += `[结束失败] ${err.message}\n`;
    }
  }

  build() {
    Column() {
      Text('HiTraceChain 分布式跟踪演示')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 20 })

      Row() {
        Button('启动跟踪链')
          .onClick(() => this.startTraceChain())
          .margin({ right: 10 })

        Button('结束跟踪链')
          .onClick(() => this.endTraceChain())
      }
      .margin({ bottom: 20 })

      Button('执行业务流程(含埋点)')
        .width('80%')
        .onClick(() => this.performBusinessFlow())
        .margin({ bottom: 20 })

      Text('跟踪日志:')
        .fontSize(16)
        .width('100%')
        .textAlign(TextAlign.Start)

      Scroll() {
        Text(this.traceLog)
          .fontSize(14)
          .fontColor('#333333')
          .width('95%')
          .textAlign(TextAlign.Start)
          .fontFamily('monospace')
      }
      .width('100%')
      .layoutWeight(1)
      .backgroundColor('#f5f5f5')
      .padding(10)
      .borderRadius(8)
      .margin({ bottom: 20 })
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

更多关于HarmonyOS 鸿蒙Next中基于HiTraceChain实现分布式调用链跟踪的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HiTraceChain分布式调用链跟踪

HarmonyOS Next中,HiTraceChain提供分布式调用链跟踪能力。它通过唯一Trace ID跨设备、跨进程跟踪请求链路,支持在分布式场景下完整追踪业务调用流程。开发者可使用HiTraceChain API在关键代码节点插入跟踪点,记录调用耗时、上下文信息。系统会自动收集和关联分布式节点上的跟踪数据,最终形成完整的调用链视图,用于性能分析和故障定位。

在HarmonyOS Next中,基于HiTraceChain实现分布式调用链跟踪,核心是通过在分布式调用链路上传递唯一的TraceId和SpanId来串联整个请求过程,并对关键节点进行打点记录。

主要步骤如下:

  1. 初始化与注入TraceId: 在请求的发起端(客户端),首先需要初始化一个调用链。使用hiTraceChain.begin()方法开始一个新的跟踪链,该方法会生成一个唯一的TraceId。这个TraceId需要被注入到本次分布式调用的初始请求中(例如,作为HTTP Header或RPC参数的一部分),以便在后续的服务中被传递。

  2. 传递上下文(Context Propagation): 这是实现分布式跟踪的关键。在服务间进行远程调用(如通过RPC、HTTP调用其他设备的Ability)时,必须将当前的TraceId以及当前的SpanId(通过hiTraceChain.getId()获取)传递到下游服务。这通常通过调用方法的入参、消息的Header或自定义的通信协议字段来实现。

  3. 创建子Span与打点: 在请求的处理端(服务端),在接收到请求后,需要从请求中解析出传递过来的TraceId和父SpanId。然后,调用hiTraceChain.begin(String name, int parentSpanId)或相关方法,以父SpanId为参数创建一个新的子Span。在这个子Span的生命周期内,你可以使用hiTraceChain.tracepoint()方法在关键的业务逻辑点或耗时操作处添加跟踪点,记录事件、状态或耗时信息。

  4. 结束Span与链: 在每个服务单元(Span)的业务处理完成后,必须调用hiTraceChain.end()来结束当前Span。在整条请求链路的最终节点,结束最顶层的Span即完成了整个调用链的跟踪。结束操作会触发该Span数据的记录或上报。

  5. 数据收集与可视化: 收集到的跟踪数据(Trace数据)会上报至你配置的监控后端或HarmonyOS的分布式跟踪系统。在那里,数据可以根据TraceId进行聚合,还原出完整的分布式调用链路图,并进行性能分析、故障定位等。

关键接口简要说明

  • hiTraceChain.begin(String name): 开始一个新的跟踪链。
  • hiTraceChain.begin(String name, int parentSpanId): 基于父SpanId开始一个子Span。
  • hiTraceChain.tracepoint(int flag, String format, Object... args): 在调用链中添加一个跟踪点。
  • hiTraceChain.end(): 结束当前的Span。
  • hiTraceChain.getId(): 获取当前的TraceId和SpanId信息,用于上下文传递。

注意事项

  • 确保TraceId和SpanId在跨进程、跨设备的调用中得到正确且无损的传递。
  • 合理规划Span的粒度,避免过细或过粗。
  • 在生产环境注意性能开销,对采样率进行配置。

通过以上方式,你可以在HarmonyOS Next的分布式应用中实现完整的调用链跟踪,从而提升系统的可观测性。

回到顶部