【android bluetooth 框架分析 02】【Module详解 13】【CounterMetrics 模块介绍】

1. CounterMetrics 介绍

CounterMetrics 模块代码很少, 我简单介绍一下。

// system/gd/metrics/counter_metrics.cc
#define LOG_TAG "BluetoothCounterMetrics"

#include "metrics/counter_metrics.h"

#include "common/bind.h"
#include "os/log.h"
#include "os/metrics.h"

namespace bluetooth {
namespace metrics {

const int COUNTER_METRICS_PERDIOD_MINUTES = 360; // Drain counters every 6 hours

const ModuleFactory CounterMetrics::Factory = ModuleFactory([]() { return new CounterMetrics(); });

void CounterMetrics::ListDependencies(ModuleList* list) const {
}

void CounterMetrics::Start() {
  alarm_ = std::make_unique<os::RepeatingAlarm>(GetHandler());
  alarm_->Schedule(
      common::Bind(&CounterMetrics::DrainBufferedCounters,
           bluetooth::common::Unretained(this)),
      std::chrono::minutes(COUNTER_METRICS_PERDIOD_MINUTES));
  LOG_INFO("Counter metrics initialized");
  initialized_ = true;
}

void CounterMetrics::Stop() {
  DrainBufferedCounters();
  initialized_ = false;
  alarm_->Cancel();
  alarm_.reset();
  LOG_INFO("Counter metrics canceled");
}

bool CounterMetrics::CacheCount(int32_t key, int64_t count) {
  if (!IsInitialized()) {
    LOG_WARN("Counter metrics isn't initialized");
    return false;
  }
  if (count <= 0) {
    LOG_WARN("count is not larger than 0. count: %s, key: %d", std::to_string(count).c_str(), key);
    return false;
  }
  int64_t total = 0;
  std::lock_guard<std::mutex> lock(mutex_);
  if (counters_.find(key) != counters_.end()) {
    total = counters_[key];
  }
  if (LLONG_MAX - total < count) {
      LOG_WARN("Counter metric overflows. count %s current total: %s key: %d",
               std::to_string(count).c_str(), std::to_string(total).c_str(), key);
      counters_[key] = LLONG_MAX;
      return false;
  }
  counters_[key] = total + count;
  return true;
}

bool CounterMetrics::Count(int32_t key, int64_t count) {
  if (!IsInitialized()) {
    LOG_WARN("Counter metrics isn't initialized");
    return false;
  }
  if (count <= 0) {
    LOG_WARN("count is not larger than 0. count: %s, key: %d", std::to_string(count).c_str(), key);
    return false;
  }
  os::LogMetricBluetoothCodePathCounterMetrics(key, count);
  return true;
}

void CounterMetrics::DrainBufferedCounters() {
  if (!IsInitialized()) {
    LOG_WARN("Counter metrics isn't initialized");
    return ;
  }
  std::lock_guard<std::mutex> lock(mutex_);
  LOG_INFO("Draining buffered counters");
  for (auto const& pair : counters_) {
    Count(pair.first, pair.second);
  }
  counters_.clear();
}

}  // namespace metrics
}  // namespace bluetooth

如果你 看过我之前其他模块的介绍。应该很容易看明白, CounterMetrics 模块对应函数的触发流程。 我这里简单的介绍一下。CounterMetrics模块的作用。

2. CounterMetrics 的功能作用是什么?

该模块主要用于 收集并定期上报蓝牙栈内部的计数型指标(Counter Metrics),其核心职责包括:

功能点解析:

  1. 缓存统计项

    • 使用 CacheCount(int32_t key, int64_t count) 将特定的计数项临时缓存在内存中(如某类事件的触发次数)。
  2. 定时上报

    • 通过 os::RepeatingAlarm 每 6 小时调用 DrainBufferedCounters(),将缓存中的计数上报给系统的 metrics 框架(如 statsd)。
  3. 线程安全

    • 内部通过 std::mutex 锁保护 counters_ map,保证并发场景下的正确性。
  4. 溢出保护

    • 如果某个计数项的总值超出 LLONG_MAX,将其钳制为 LLONG_MAX 并发出警告。

3. 设计该模块的目的是什么?

背后的设计理念:

设计需求说明
低频统计上传某些蓝牙事件(如连接失败次数、重连次数、A2DP 播放错误等)不适合立即上报或日志输出。
延迟处理,降低性能影响延迟上报避免频繁调用 I/O 操作(如写文件、上报 statsd)。
可扩展性强只需新增对应的 key,即可添加新的统计项,无需修改上层逻辑。
帮助调优与问题排查比如分析 Bluetooth 启动失败次数、配对错误数,辅助 Google 收集大数据做产品改进。

4. 如果去掉这个模块会怎样?

  1. 无法延迟上报

    • 每次计数都需要即时上报,性能开销显著增加。
  2. 缺失统计数据

    • 某些只有内部记录但未及时上报的数据将无法收集,影响用户反馈分析与 QA 问题定位。
  3. 不利于数据分析平台接入

    • Google 的 statsd、OEM 的大数据平台等依赖此模块的统一接口上传蓝牙计数指标。

5. 实际应用场景举例(车机)

场景CounterMetrics 的作用
A2DP 播放中断记录播放异常次数,辅助分析车机蓝牙不稳定问题
HFP 通话失败统计通话连接失败次数,用于判断兼容性问题
蓝牙重启频率如果蓝牙频繁崩溃,CounterMetrics 可以记录频率帮助开发定位根因
配对异常统计不同品牌手机配对失败的频率,为白名单机制提供数据

6. 总结

项目内容
模块名称CounterMetrics
主要功能缓存并定期上报蓝牙内部计数数据
设计意义降低性能开销、支持延迟上报、提高调试能力
可否去除不能,否则将严重影响日志分析、问题定位及大数据支持能力

PS:
车机/手机 中 如果要对蓝牙服务 埋点, 诊断等。 其实可以结合这个模块来添加。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值