预先可观察性的仪器代码是开发人员可以为自己的未来自我做的最重要的事情之一。用Datadog和Golang观察AWS Lambda的乐器实际上比您想象的要简单得多。那是什么意思?
定义
可观察性是在任何给定时间测量系统状态的能力,了解其表现和行为的表现,并在需要检查的情况下为每个操作提供适当的可见性。我最熟悉的三个支柱是指标,痕迹和日志。我没有自称是该主题的专家,但我确实了解能够大规模观察我的服务和团队服务意味着什么。
首先,要正确完成仪器(甚至只是尝试完成)非常重要。通过这样做,当事情确实进入生产时,您可以在手指技巧上获得数据,以便能够在监视这些服务以达到其服务水平协议和服务水平的目标之外,以解决这些问题。<<<<<<< /p>
这篇文章不会从理论上谈论您如何做到这一点,而是专门向您展示了如何设置它并部署它,以便您可以看到与Golang和Datadog的观察到的LAMBDA的确如此。在过去的几年中,我一直是Datadog的忠实拥护者,老实说,目前正在与我职业生涯中一些最好的工具合作。希望这对您进行类似的事情
时有所帮助我们需要什么?
假设生产中正在发生问题,但是您每小时会收到数千个事件,并且您可以轻松地跟踪代码的有问题的块。想象一下,当您拥有一个非常分布式的系统时,这甚至会变得很难,许多Lambdas或ECS任务或EKS任务正在运行,并且您可以确定哪个实际上是在引起问题。
您所知道的就是客户打电话给您的支持团队,他们向您提醒您问题。而且它并不是一直在发生,但实际上是在干草堆里的一针。当您有成千上万的客户时,似乎并不是一个问题……只是告诉他们刷新。
但是,如果下面有一些使它以同样的方式一遍又一遍地发生的事情怎么办?听起来很艰巨。可以。但是,如果您在前做事,那就不必做。返回指标,迹线和日志,让我们将指标放在一点点,然后专注于日志。
Golang日志级别
首先,您需要确保与适量的内容正确登录正确的级别。让我们离开桌子,然后讨论您要发送内容的层次。在生产中,我喜欢以错误级别发送内容,但我总是喜欢能够通过环境变量即时调整我的日志级别的能力。使用CDK时,我通常会做类似的事情
new GoFunction(this, `SampleFunc`, {
entry: path.join(__dirname, `../src/source`),
functionName: `func-name`,
environment: {
"DD_FLUSH_TO_LOG": "true",
"DD_TRACE_ENABLED": "true",
"LOG_LEVEL": getLogLevel(props.stage) // this nugget right here
},
});
通过将LOG_LEVEL
环境变量添加到此lambda中,如果我想强迫更多的详细信息,我可以更改它。
以下是一个简单的示例,您可以添加更多默认逻辑,但这可以从
中传递的变量设置日志级别
lib.SetLevel(os.Getenv("LOG_LEVEL"))
在示例中,我使用了非常流行的logrus库,然后我将日志格式化为json
package main
import (
"context"
"os"
ddlambda "github.com/DataDog/datadog-lambda-go"
log "github.com/sirupsen/logrus"
)
func init() {
log.SetFormatter(&log.JSONFormatter{
PrettyPrint: false,
})
lib.SetLevel(os.Getenv("LOG_LEVEL"))
}
func main() {
lambda.Start(ddlambda.WrapFunction(handler, lib.DataDogConfig()))
}
func handler(ctx context.Context, event interface{}) error {
// you'd NOT use interface{} as the event
return nil
}
AWS lambda记录输出
上面的作用是设置日志库以输出JSON,并且它将写入CloudWatch。我通常在CloudWatch中将日志保留设置为一天,因为我会一直将所有内容运送到Datadog。这就是Datadog中输出的样子。从右边的事件属性中可以使用,一切都很好和分类。使用JSON真正很酷的事情是Datadog将显示对您的超级好。
in命令输出其他元素,logrus我使用with fields记录func。
log.WithFields(
log.Fields{
"somethingInJson": theObject,
}).Debug("Logging out the object")
所以这很酷。日志进入DataDog。但是这是怎么发生的?我不会在这里跳过篮球,以便如何使用DD做到这一点,而是随意阅读他们的documentation。太棒了。只知道您有选择。 lambda扩展名,转货或资源编译。
观察迹线
在应用程序中进行跟踪只是您启动代码的一种方式,以便在上下文中收集请求或事件或任何触发的请求。跟踪是所有子项目相关的父上下文。如果您在一分钟内得到1,000个请求,则将有1,000个痕迹。
然后,在每个轨迹的内部,您都会有事物称为跨度。跨度也可以嵌套,以便您执行的每个功能或块获得特定的属性,以识别
- 名称
- 时间开始
- 持续时间
除了能够对这些特定的操作进行分组之外,这有助于解决事情的时间。同样,当将lambda与golang和datadog一起使用时,工具确实做得很好,而datadog go库使其非常简单。
让我们首先看一下它的出现。请记住,痕迹具有跨度和跨度可以在该父跨度内有孩子跨度
第一件事是火焰图是查看跨度的真正好方法。在这里,Datadog在下面为我做什么
您可以看到顶级跨度是lambda本身的执行。然后在那个跨度内,我接到了DynamoDB的电话,然后打电话给SQS,将事件放在队列上。还要注意每个跨度的时间百分比,然后是每个跨度所代表的持续时间。在这里,当垂直查看为列表
时,它再次是func handler(ctx context.Context, event interface{}) error {
span, _ := tracer.SpanFromContext(ctx)
// more code here
}
和跟踪AWS库也很简单。除包装客户端库外,您还需要在请求中包括上下文。对于DynamoDB,这是如何做到的。请注意使用Datadog库包装
package lib
import (
"context"
"fmt"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/bix-digital/golang-fhir-models/fhir-models/fhir"
awstrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/aws/aws-sdk-go/aws"
)
// NewDynamoDBClient inits a DynamoDB session to be used throughout the services
func NewDynamoDBClient() *dynamodb.DynamoDB {
c := &aws.Config{
Region: aws.String("us-west-2"),
}
sess := session.Must(session.NewSession(c))
sess = awstrace.WrapSession(sess,
awstrace.WithAnalytics(true),
awstrace.WithAnalyticsRate(1.0))
return dynamodb.New(sess)
}
// in another file or func
// make a call to DynaomDB
_, err = d.db.PutItemWithContext(ctx, itemInput)
非常简单,对吗?跟踪和个人都跨越了连接,如果您遵循DD的指导如何推入帐户,则会获得那些不错的火焰图和跨度列表。如果您偶然地追踪HTTP请求,我有一篇文章,您应该查看next
将它们连接在一起
所以我们有痕迹(跨度)和日志。请记住,我说我们稍后涵盖指标。但是在生产中,如果我有痕迹/跨度和日志有线,我可以过滤在记录错误的日志上,无论是lambda还是ECS任务(或其他),我都可以轻松找到有问题的组件。使用golang lib观察那些用datadog观察那些lambdas,使这个超级简单 -
func handler(ctx context.Context, event interface{}) error {
span, _ := tracer.SpanFromContext(ctx)
newCtx := context.WithValue(ctx, "correlationId", event.MetaDetails.CorrelationId)
log.WithFields(
log.Fields{
"event": event,
"span_id": span.Context().SpanID(),
"trace_id": span.Context().TraceID(),
"correlationId": newCtx.Value("correlationId"),
}).Debugf("Logging out the event")
}
一旦我们有了新的跨度,每个跨度将按DD分配一个跨度ID,然后在该跨度内,我们就可以访问跟踪ID本身。如果您使用跨度和跟踪ID登录事物,那么您将获得所需的连接性。在Datadog应用程序中,您可以轻松地看到这些日志与给定的跨度相关联,反之亦然。您可以从日志查看器开始,并在需要的话上旋转到APM侧。下面的简单视图显示了与此跟踪关联的信息和调试级别日志
关于所有这一切的最后一件事要注意。您可能会在上面的代码中看到此字段称为“相关性”,该字段正在登录。为什么???简单的。想象一下,一个事件触发了上游的事物,一个事件降落在12个功能,8个队列和3个运动流中。能够追踪事件的整体延迟是否不错?甚至在一个特定事件中追踪失败?如果向用户呈现错误并显示了他们的TraceId,则可以找到特定的交易并进行故障排除。借助DataDog,您可以将其用于日志语句的方面,然后对其进行过滤。有关更多阅读,此article可能是一个很好的起点。
用Datadog和Golang结束观察Lambdas
在这一个细节中有很多细节,但希望它显示了一些模式和设置,用于观察AWS lambdas,golang和datadog可以完成可观察性的3个关键组成部分中的2个。日志,痕迹和指标。我可能会发表有关指标以及为什么有用的文章。但是,如果您正在做基于云的分布式系统,我认为至少具有日志和痕迹,并且至少将它们连接在一起会给您一个很好的起点。可观察性是不自由的。您必须启动您的代码,但是当您有任何类型的卷时,您在生产中遇到的第一期不仅仅是为自己付费。