函数里的日志与埋点
从函数里主动发出日志和 span,才能在生产环境监控和排查。这篇讲支持哪些遥测类型、怎么写、以及日志的最佳实践。
https://www.palantir.com/docs/foundry/functions/instrumentation-telemetry/
原始标题:Function management > Instrumentation and telemetry
先记住这几条
写在前面
你可以从函数里主动发出某些类型的遥测数据,用来监控和排查生产环境的工作流。
想了解如何查看函数发出的遥测数据,参见本体与 AIP 可观测性文档。
支持的遥测类型
支持的遥测类型
下表概览了每种函数语言支持的遥测类型。无论哪种函数,平台都会自动创建一个覆盖函数整个执行时长的 span,以及一条请求日志。
| 语言 | 日志 | Span | 指标 |
|---|---|---|---|
| TypeScript v1 | 支持 | 仅平台预定义的 span[1] | 仅平台预定义的指标[2] |
| TypeScript v2 | 支持 | 支持[3] | 仅平台预定义的指标[2] |
| Python | 支持 | 支持[3] | 仅平台预定义的指标[2] |
[1] TypeScript v1 函数里平台预定义的 span 包括对象加载、查询执行这类操作。
[2] Foundry 会为所有类型的函数记录总执行时长。
[3] TypeScript v2 与 Python 函数会自动为所有出向网络请求打点,此外你也可以自己添加自定义 span。
Logs
你可以从函数里发出自定义日志,并在事后回看。下面的例子演示了 TypeScript v1、TypeScript v2 和 Python 函数分别怎么打日志。
在 TypeScript v2 函数里,Foundry 会帮你初始化 OpenTelemetry SDK 的全局 logger provider,你可以从它那里取到一个 logger。如果你想用第三方日志库,必须把它们配置成通过从全局 logger provider 取到的 logger 来输出日志。
export class MyFunctions {
@Function()
public myFunction(name: string): string {
console.log(`This is a custom log line, ${name}.`);
return `Hello, ${name}!`;
}
}import { logs } from "@opentelemetry/api-logs";
const logger = logs.getLogger("my-function");
export default function myFunction(name: string): string {
logger.emit({
body: "This is a custom log line.",
attributes: {
name
},
});
// 也可以直接用全局的 console 对象
console.log(`This is a custom log line, ${name}.`);
return `Hello, ${name}!`;
}import logging
from functions.api import function
logger = logging.getLogger(__name__)
@function
def my_function(name: str) -> str:
logger.info("This is a custom log line.")
return f"Hello, {name}!"Logging best practices
打日志请遵循下面这些做法:
- 选对日志级别: 正常操作用
INFO,可恢复的问题用WARN,失败用ERROR,详细诊断信息用DEBUG。 - 带上相关上下文: 加上标识符、数量、操作细节,便于理解执行过程。
- 不要打敏感数据: 不要记录凭据、可能含敏感信息的完整 API 响应,或其他涉密内容。
关于如何写好日志、查看服务日志、按级别过滤,参见服务日志与调试。
Spans
你也可以在 TypeScript v2 和 Python 函数里创建自定义 span,用来跟踪某个具体操作耗时多久。下面的例子演示了如何创建自定义 span。
在 TypeScript v2 和 Python 函数里,Foundry 会帮你初始化 OpenTelemetry SDK 的全局 tracer provider,你可以从它那里取到一个 tracer。如果你想用第三方链路追踪库,必须把它们配置成通过从全局 tracer provider 取到的 tracer 来输出追踪数据。
import { trace } from "@opentelemetry/api";
import { Integer } from "@osdk/functions";
const tracer = trace.getTracer("my-function");
export default function sqrt(n: Integer): Integer {
const sqrt = tracer.startActiveSpan("my-custom-span", (span) => {
try {
return Math.sqrt(n);
} finally {
span.end();
}
});
return sqrt;
}import math
from functions.api import function
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
@function
def sqrt(n: int) -> int:
with tracer.start_as_current_span("my-custom-span"):
return math.sqrt(n)延伸阅读 · 相关页面
按主题横向跳转,不必顺着目录一篇篇读。