otel-expo-style
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOTel Expo Style
Expo 环境下的 OTel 实践规范
Preserve existing runtime guards. If the app avoids native SDKs in Expo Go or an
unsupported runtime branch, initialize OTel only inside the supported branch.
ts
const isExpoGo = process.env.EXPO_PUBLIC_RUNTIME === "expo-go";
if (!isExpoGo) {
initObservability();
Sentry.init({ dsn: process.env.EXPO_PUBLIC_SENTRY_DSN });
}
registerRootComponent(App);In supported builds, call before Sentry and before app
registration/user code.
initObservability()保留现有的运行时防护机制。如果应用在Expo Go或不支持的运行时分支中避免使用原生SDK,则仅在支持的分支内初始化OTel。
ts
const isExpoGo = process.env.EXPO_PUBLIC_RUNTIME === "expo-go";
if (!isExpoGo) {
initObservability();
Sentry.init({ dsn: process.env.EXPO_PUBLIC_SENTRY_DSN });
}
registerRootComponent(App);在支持的构建版本中,需在初始化Sentry以及注册应用/执行用户代码之前调用。
initObservability()SDK Shape
SDK 结构规范
Use native OTel JS APIs and browser/mobile-compatible providers/exporters. Do
not create , , or tracking-specific helper
files.
recordCountersendSuperlogSpants
export const tracer = trace.getTracer("mugline.mobile");
export const meter = metrics.getMeter("mugline.mobile");
export const ordersSubmitted = meter.createCounter("mug.orders.submitted");Add automatic fetch/XHR instrumentation when compatible so API calls get spans
without wrapping application code.
使用原生OTel JS API以及兼容浏览器/移动端的提供方/导出器。请勿创建、或特定于追踪的辅助文件。
recordCountersendSuperlogSpants
export const tracer = trace.getTracer("mugline.mobile");
export const meter = metrics.getMeter("mugline.mobile");
export const ordersSubmitted = meter.createCounter("mug.orders.submitted");在兼容情况下添加自动fetch/XHR工具,使API调用无需封装应用代码即可生成追踪跨度。
Product Actions
产品操作追踪
Wrap low-risk business operations with native active spans.
ts
await tracer.startActiveSpan("mug.order.submit", async (span) => {
try {
span.setAttribute("tenant.id", tenantId);
ordersSubmitted.add(1, { "tenant.id": tenantId, outcome: "success" });
} catch (error) {
span.recordException(error as Error);
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
});使用原生活跃追踪跨度包裹低风险业务操作。
ts
await tracer.startActiveSpan("mug.order.submit", async (span) => {
try {
span.setAttribute("tenant.id", tenantId);
ordersSubmitted.add(1, { "tenant.id": tenantId, outcome: "success" });
} catch (error) {
span.recordException(error as Error);
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
});Configuration
配置方式
Inline the endpoint and ingest key directly in the observability module. The
key is project-scoped + write-only (Sentry-DSN shaped), so source-level
configuration is the right default for Expo — and it sidesteps the
build-time-vs-runtime quirks of env vars in different
build profiles.
EXPO_PUBLIC_*ts
const SUPERLOG_ENDPOINT = "https://intake.superlog.sh";
const SUPERLOG_KEY = "superlog_live_…"; // set by superlog-onboard skill on pairing
const SERVICE_NAME = "mugline-mobile";
const exporter = new OTLPTraceExporter({
url: `${SUPERLOG_ENDPOINT}/v1/traces`,
headers: { authorization: `Bearer ${SUPERLOG_KEY}` },
});将端点和接入密钥直接内联到可观测性模块中。该密钥是项目级别的只读密钥(格式类似Sentry-DSN),因此源码级别的配置是Expo环境下的合理默认方案——这也规避了不同构建配置中环境变量在构建时与运行时的特性差异。
EXPO_PUBLIC_*ts
const SUPERLOG_ENDPOINT = "https://intake.superlog.sh";
const SUPERLOG_KEY = "superlog_live_…"; // set by superlog-onboard skill on pairing
const SERVICE_NAME = "mugline-mobile";
const exporter = new OTLPTraceExporter({
url: `${SUPERLOG_ENDPOINT}/v1/traces`,
headers: { authorization: `Bearer ${SUPERLOG_KEY}` },
});