API 文档

编辑

本节介绍 API 中最常用的部分。

Go 代理使用标准 godoc 进行文档编写。有关完整文档,请参阅 pkg.go.dev/go.elastic.co/apm/v2 上的文档,或使用 "godoc" 工具。

跟踪器 API

编辑

您的应用程序与 Go 代理的初始接触点是 apm.Tracer 类型,该类型提供了报告事务和错误的方法。

为了简化检测,Go 代理提供了一个初始化函数 apm.DefaultTracer()。此跟踪器在首次调用 apm.DefaultTracer() 时初始化,并在后续调用时返回。可以使用 apm.SetDefaultTracer(tracer) 修改此函数返回的跟踪器。调用此函数将关闭先前存在的任何默认跟踪器。此跟踪器使用环境变量进行配置;有关详细信息,请参阅 配置

import (
	"go.elastic.co/apm/v2"
)

func main() {
	tracer := apm.DefaultTracer()
	...
}

事务

编辑

func (*Tracer) StartTransaction(name, type string) *Transaction

编辑

StartTransaction 返回一个新的事务,其中包含指定的名称和类型,并将开始时间设置为当前时间。如果您需要设置时间戳或父 跟踪上下文,请使用 Tracer.StartTransactionOptions

此方法应在事务的开始时调用,例如 Web 或 RPC 请求。例如:

transaction := apm.DefaultTracer().StartTransaction("GET /", "request")

事务将在 Elastic APM 应用程序中按类型和名称分组。

启动事务后,您可以记录结果并添加上下文以进一步描述该事务。

transaction.Result = "Success"
transaction.Context.SetLabel("region", "us-east-1")

有关设置事务上下文的更多详细信息,请参阅 上下文

func (*Tracer) StartTransactionOptions(name, type string, opts TransactionOptions) *Transaction

编辑

StartTransactionOptions 本质上与 StartTransaction 相同,但也接受选项结构。此结构允许您指定父 跟踪上下文和/或事务的开始时间。

opts := apm.TransactionOptions{
	Start: time.Now(),
	TraceContext: parentTraceContext,
}
transaction := apm.DefaultTracer().StartTransactionOptions("GET /", "request", opts)

func (*Transaction) End()

编辑

End 将事务排队,以便发送到 Elastic APM 服务器。在此之后不得修改事务,但仍可用于启动跨度。

事务的持续时间计算为事务开始到此调用之间经过的时间量。要覆盖此行为,可以在调用 End 之前设置事务的 Duration 字段。

transaction.End()

func (*Transaction) TraceContext() TraceContext

编辑

TraceContext 返回事务的 跟踪上下文

func (*Transaction) EnsureParent() SpanID

编辑

EnsureParent 返回事务的父跨度 ID,如果之前没有父跨度 ID,则生成并记录一个。

EnsureParent 启用与 JavaScript 真实用户监控 (RUM) 代理为初始页面加载创建的跨度的关联。如果您的后端服务动态生成 HTML 页面,则可以将跟踪和父跨度 ID 注入到页面中,以便初始化 JavaScript RUM 代理,从而使 Web 浏览器的页面加载显示为跟踪的根。

var initialPageTemplate = template.Must(template.New("").Parse(`
<html>
<head>
<script src="elastic-apm-js-base/dist/bundles/elastic-apm-js-base.umd.min.js"></script>
<script>
  elasticApm.init({
    serviceName: '',
    serverUrl: 'https://127.0.0.1:8200',
    pageLoadTraceId: {{.TraceContext.Trace}},
    pageLoadSpanId: {{.EnsureParent}},
    pageLoadSampled: {{.Sampled}},
  })
</script>
</head>
<body>...</body>
</html>
`))

func initialPageHandler(w http.ResponseWriter, req *http.Request) {
	err := initialPageTemplate.Execute(w, apm.TransactionFromContext(req.Context()))
	if err != nil {
		...
	}
}

有关更多信息,请参阅 JavaScript RUM 代理文档

func (*Transaction) ParentID() SpanID

编辑

ParentID 返回事务的父级的 ID,如果事务没有父级,则返回零(无效)SpanID。

func ContextWithTransaction(context.Context, *Transaction) context.Context

编辑

ContextWithTransaction 将事务添加到上下文中,并返回结果上下文。

可以使用 apm.TransactionFromContext 检索事务。上下文也可以传递到 apm.StartSpan,后者在底层使用 TransactionFromContext 创建一个作为事务子级的跨度。

func TransactionFromContext(context.Context) *Transaction

编辑

TransactionFromContext 返回之前使用 apm.ContextWithTransaction 存储在上下文中的事务,如果上下文不包含事务,则返回 nil。

func DetachedContext(context.Context) context.Context

编辑

DetachedContext 返回一个新的上下文,该上下文与输入的生命周期分离,但仍返回与输入相同的值。

DetachedContext 可用于维护关联事件所需的跟踪上下文,但该操作是“即发即忘”的,不应受到周围上下文的截止时间或取消的影响。

func TraceFormatter(context.Context) fmt.Formatter

编辑

TraceFormatter 返回 fmt.Formatter 的一个实现,该实现可用于格式化存储在提供的上下文中的事务和跨度的 ID。

格式化程序理解以下格式:

  • %v: 跟踪 ID、事务 ID 和(如果在跨度上下文中)跨度 ID,以空格分隔
  • %t: 仅跟踪 ID
  • %x: 仅事务 ID
  • %s: 仅跨度 ID

可以使用 "+" 选项以 "key=value" 样式格式化值,字段名称为 trace.idtransaction.idspan.id。例如,使用 "%+v" 作为格式将生成 "trace.id=…​ transaction.id=…​ span.id=…​"。

有关更深入的示例,请参阅 手动日志关联(非结构化)

跨度

编辑

为了描述事务中的活动,我们创建跨度。Go 代理内置了对某些活动(例如数据库查询)生成跨度的支持。您可以使用 API 报告特定于您的应用程序的跨度。

func (*Transaction) StartSpan(name, spanType string, parent *Span) *Span

编辑

StartSpan 在事务中启动并返回一个新的跨度,其中包含指定的名称、类型和可选的父跨度,并将开始时间设置为当前时间。如果您需要设置时间戳或父 跟踪上下文,请使用 Transaction.StartSpanOptions

如果跨度类型包含两个点,则假定它们分隔跨度类型、子类型和操作;一个点分隔跨度类型和子类型,并且不会设置操作。

如果对事务进行了采样,则将设置跨度的 ID,并且如果相应地配置了跟踪器,则将设置其堆栈跟踪。如果未对事务进行采样,则在调用其 End 方法时,将以静默方式丢弃返回的跨度。为了避免为这些丢弃的跨度进行任何不必要的计算,请调用 Dropped 方法。

为了方便起见,在 nil 事务上创建跨度是有效的;生成的跨度将是非 nil 的并且可以安全使用,但不会报告给 APM 服务器。

span := tx.StartSpan("SELECT FROM foo", "db.mysql.query", nil)

func (*Transaction) StartSpanOptions(name, spanType string, opts SpanOptions) *Span

编辑

StartSpanOptions 本质上与 StartSpan 相同,但也接受选项结构。此结构允许您指定父 跟踪上下文和/或跨度的开始时间。如果选项中未指定父跟踪上下文,则跨度将是事务的直接子级。否则,父跟踪上下文应属于从事务派生的某个跨度。

opts := apm.SpanOptions{
	Start: time.Now(),
	Parent: parentSpan.TraceContext(),
}
span := tx.StartSpanOptions("SELECT FROM foo", "db.mysql.query", opts)

func StartSpan(ctx context.Context, name, spanType string) (*Span, context.Context)

编辑

StartSpan 在上下文(如果有)中启动并返回采样事务和父跨度中的新跨度。如果跨度未被丢弃,则它将包含在结果上下文中。

span, ctx := apm.StartSpan(ctx, "SELECT FROM foo", "db.mysql.query")

func (*Span) End()

编辑

End 将跨度标记为完成。在此之后不得修改跨度,但仍可用作跨度的父级。

跨度的持续时间将计算为跨度开始到此调用之间经过的时间量。要覆盖此行为,可以在调用 End 之前设置跨度的 Duration 字段。

func (*Span) Dropped() bool

编辑

Dropped 指示跨度是否被丢弃,这意味着它不会报告给 APM 服务器。当使用 nil 或未采样的事务创建跨度,或者已达到其最大跨度限制时,跨度将被丢弃。

func (*Span) TraceContext() TraceContext

编辑

TraceContext 返回跨度的 跟踪上下文

func ContextWithSpan(context.Context, *Span) context.Context

编辑

ContextWithSpan 将跨度添加到上下文中,并返回结果上下文。

可以使用 apm.SpanFromContext 检索跨度。上下文也可以传递到 apm.StartSpan,后者在底层使用 SpanFromContext 创建另一个作为跨度子级的跨度。

func SpanFromContext(context.Context) *Span

编辑

SpanFromContext 返回一个之前使用 apm.ContextWithSpan 存储在上下文中的 span,如果上下文中不包含 span 则返回 nil。

func (*Span) ParentID() SpanID

编辑

ParentID 返回 span 的父 span 的 ID。

上下文 (Context)

编辑

在报告事务和错误时,您可以提供上下文来描述这些事件。内置的检测通常会提供一些上下文,例如 HTTP 请求的 URL 和远程地址。您还可以提供自定义上下文和标签。

func (*Context) SetLabel(key string, value interface{})

编辑

SetLabel 使用给定的键值对标记事务或错误。如果键包含任何特殊字符 (., *, "),它们将被替换为下划线。

如果值是数值或布尔值,则它将作为 JSON 数字或布尔值发送到服务器;否则,它将转换为字符串,必要时使用 fmt.Sprint。服务器从 6.7 版本开始支持数值和布尔值。

长度超过 1024 个字符的字符串值将被截断。标签在 Elasticsearch 中被索引为关键字字段。

在使用标签之前,请确保您了解可用的不同类型的 元数据

避免定义过多的用户指定的标签。在索引中定义过多的唯一字段是一种可能导致 映射爆炸 的情况。

func (*Context) SetCustom(key string, value interface{})

编辑

SetCustom 用于向事务或错误添加自定义的、非索引的上下文信息。如果键包含任何特殊字符 (., *, "),它们将被替换为下划线。

非索引意味着数据在 Elasticsearch 中不可搜索或聚合,您无法在此数据之上构建仪表板。但是,非索引信息对于其他原因很有用,例如提供上下文信息以帮助您快速调试性能问题或错误。

该值可以是任何可以使用 encoding/json 编码的类型。

在使用自定义上下文之前,请确保您了解可用的不同类型的 元数据

func (*Context) SetUsername(username string)

编辑

SetUsername 记录与事务关联的用户的用户名。

func (*Context) SetUserID(id string)

编辑

SetUserID 记录与事务关联的用户的 ID。

func (*Context) SetUserEmail(email string)

编辑

SetUserEmail 记录与事务关联的用户的电子邮件地址。

错误

编辑

Elastic APM 提供了两种捕获错误事件的方法:报告错误日志记录和报告“异常”(在 Go 术语中是 panic 或 error)。

func (*Tracer) NewError(error) *Error

编辑

NewError 返回一个从 err 获取详细信息的新 Error。

异常消息将设置为 err.Error()。异常模块和类型将分别设置为错误的包名称和类型名称,其中原因的定义与 github.com/pkg/errors 给出的定义相同。

e := apm.DefaultTracer().NewError(err)
...
e.Send()

提供的错误可以实现多个接口中的任何一个,以提供其他信息。

// Errors implementing ErrorsStacktracer will have their stacktrace
// set based on the result of the StackTrace method.
type ErrorsStacktracer interface {
    StackTrace() github.com/pkg/errors.StackTrace
}

// Errors implementing Stacktracer will have their stacktrace
// set based on the result of the StackTrace method.
type Stacktracer interface {
    StackTrace() []go.elastic.co/apm/v2/stacktrace.Frame
}

// Errors implementing Typer will have a "type" field set to the
// result of the Type method.
type Typer interface {
	Type() string
}

// Errors implementing StringCoder will have a "code" field set to the
// result of the Code method.
type StringCoder interface {
	Code() string
}

// Errors implementing NumberCoder will have a "code" field set to the
// result of the Code method.
type NumberCoder interface {
	Code() float64
}

使用 NewError 创建的错误将填充唯一的 ID 作为其 ID 字段。这可以在您的应用程序中用于关联。

func (*Tracer) NewErrorLog(ErrorLogRecord) *Error

编辑

NewErrorLog 返回给定 ErrorLogRecord 的新 Error。

type ErrorLogRecord struct {
	// Message holds the message for the log record,
	// e.g. "failed to connect to %s".
	//
	// If this is empty, "[EMPTY]" will be used.
	Message string

	// MessageFormat holds the non-interpolated format
	// of the log record, e.g. "failed to connect to %s".
	//
	// This is optional.
	MessageFormat string

	// Level holds the severity level of the log record.
	//
	// This is optional.
	Level string

	// LoggerName holds the name of the logger used.
	//
	// This is optional.
	LoggerName string

	// Error is an error associated with the log record.
	//
	// This is optional.
	Error error
}

生成的 Error 的日志堆栈跟踪将不会设置。调用 SetStacktrace 方法来设置它。

e := apm.DefaultTracer().NewErrorLog(apm.ErrorLogRecord{
	Message: "Somebody set up us the bomb.",
})
...
e.Send()

func (*Error) SetTransaction(*Transaction)

编辑

SetTransaction 将错误与给定的事务相关联。

func (*Error) SetSpan(*Span)

编辑

SetSpan 将错误与给定的 span 以及 span 的事务相关联。调用 SetSpan 时,不需要同时调用 SetTransaction。

func (*Error) Send()

编辑

Send 将错误排队,以便发送到 Elastic APM 服务器。

func (*Tracer) Recovered(interface{}) *Error

编辑

Recovered 从恢复的值返回一个 Error,可以选择将其与事务关联。错误不会被发送;设置错误的上下文,然后调用其 Send 方法是调用者的责任。

tx := apm.DefaultTracer().StartTransaction(...)
defer tx.End()
defer func() {
	if v := recover(); v != nil {
		e := apm.DefaultTracer().Recovered(v)
		e.SetTransaction(tx)
		e.Send()
	}
}()

func CaptureError(context.Context, error) *Error

编辑

CaptureError 返回一个与上下文中存在的已采样事务和 span 相关的的新错误(如果有),并使用给定的错误设置其异常详细信息。Error.Handled 字段将设置为 true,并设置堆栈跟踪。

如果上下文中没有事务,或者该事务未被采样,则 CaptureError 返回 nil。为了方便起见,如果提供的错误为 nil,则 CaptureError 也将返回 nil。

if err != nil {
        e := apm.CaptureError(ctx, err)
        e.Send()
}

跟踪上下文 (Trace Context)

编辑

跟踪上下文包含事务或 span 的 ID、事务或 span 所属的端到端跟踪的 ID 以及与采样相关的标志等跟踪选项。跟踪上下文在进程之间传播,例如在 HTTP 标头中,以便关联来自相关服务的事件。

Elastic APM 的跟踪上下文基于 W3C 跟踪上下文草案。

错误上下文 (Error Context)

编辑

错误可以像事务一样与上下文关联。有关详细信息,请参见 上下文。此外,可以使用 SetTransactionSetSpan 将错误分别与活动事务或 span 关联。

tx := apm.DefaultTracer().StartTransaction("GET /foo", "request")
defer tx.End()
e := apm.DefaultTracer().NewError(err)
e.SetTransaction(tx)
e.Send()

Tracer 配置

编辑

许多配置属性可以通过 apm.Tracer 方法调用动态更新。有关详细信息,请参阅 pkg.go.dev/go.elastic.co/apm/v2#Tracer 的文档。配置方法主要以 Set 为前缀,例如 apm#Tracer.SetLogger