站長阿川

站長阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

站長精心設計,帶你實作 63 個小專案,得到作品集!

立即開始免費試讀!

我是一個人

介紹

我們最近上線了一個新應用,想引入外部監控。我們一直在糾結是使用 N 公司的服務還是完全在 AWS 內部部署,最後我們決定使用Datadog

即使在網上搜尋之後,我仍然找不到太多關於如何使用Next.js + ECS Fargate配置安裝 Datadog 的訊息,所以我將記錄我實際採取的步驟。

20250307102727.png

我想要做什麼

我想將我的應用程式日誌APM 資料都傳送到 Datadog。

由於現有的基礎設施是使用CDK進行管理的,我們希望使用CDK來建立合適的架構。

CDK 變更(僅差異)

新增 Secrets Manager 來儲存您的 Datadog API 金鑰。

從 ECS 連線時,您需要設定一個金鑰,但您可以從 Datadog 的「組織設定」→「API 金鑰」取得和更新金鑰。

當您第一次連線到 ECS 時,API 金鑰也會顯示在待機畫面上的設定檔中。

部署 Secrets Manager 後,新增您獲得的金鑰。

// Datadog API キー用シークレットの作成
const datadogSecret = new secretsmanager.Secret(this, 'DatadogSecret', {
  secretName: `${props.envName}-${props.projectName}-datadog-api-key`,
  description: 'Datadog API Key - Update manually after deployment',
  secretStringValue: cdk.SecretValue.unsafePlainText('placeholder-update-manually'),
});
datadogSecret.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN);

// タスク実行ロールにDatadogシークレットへのアクセス権限を付与
datadogSecret.grantRead(executionRole);

主容器設定

我們使用 FireLens,因為將 ECS 日誌直接傳送到 Datadog 比透過 CloudWatch 更便宜。

const clientContainer = serviceTaskDefinition
  .addContainer('client', {
    image: appImage,
    logging: ecs.LogDrivers.firelens({
      options: {
        Name: 'datadog',
        Host: 'http-intake.logs.ap1.datadoghq.com',
        TLS: 'on',
        dd_service: 'service_name',
        dd_source: 'nodejs',
        dd_tags: `env:${props.envName}`,
        provider: 'ecs',
      },
      secretOptions: {
        apikey: ecs.Secret.fromSecretsManager(datadogSecret),
      },
    }),
    environment: {
      // ... 他の環境変数
      DD_ENV: props.envName,
      DD_SERVICE: 'service_name',
      DD_VERSION: props.imageTag,
      DD_LOGS_INJECTION: 'true',
      DD_AGENT_HOST: '127.0.0.1',
      OTEL_TRACES_EXPORTER: 'otlp',
      OTEL_EXPORTER_OTLP_PROTOCOL: 'http/protobuf',
      OTEL_EXPORTER_OTLP_ENDPOINT: 'http://127.0.0.1:4318',
      OTEL_SERVICE_NAME: 'service_name',
      OTEL_RESOURCE_ATTRIBUTES: `deployment.environment=${props.envName},service.version=${props.imageTag}`,
    },
    // ...
  });

Datadog Agent 邊車容器

DD_SITE必須設定為您正在使用的 Datadog 的區域。

請注意,如果設定不正確,則不會發送日誌。

對於東京地區,該地址為ap1.datadoghq.com

const datadogLogGroup = new logs.LogGroup(this, 'DatadogLogGroup', {
  logGroupName: `/aws/ecs/datadog/${props.envName}`,
  retention: logs.RetentionDays.THREE_MONTHS,
  removalPolicy: props.envName === 'prd' ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
});

const datadogContainer = serviceTaskDefinition.addContainer('datadog-agent', {
  image: ecs.ContainerImage.fromRegistry('public.ecr.aws/datadog/agent:latest'),
  memoryLimitMiB: 512,
  containerName: 'datadog',
  essential: false,
  logging: ecs.LogDriver.awsLogs({
    streamPrefix: 'datadog',
    logGroup: datadogLogGroup,
  }),
  secrets: {
    DD_API_KEY: ecs.Secret.fromSecretsManager(datadogSecret),
  },
  environment: {
    ECS_FARGATE: 'true',
    DD_APM_ENABLED: 'true',
    DD_APM_NON_LOCAL_TRAFFIC: 'true',
    DD_SITE: 'ap1.datadoghq.com',
    DD_LOGS_ENABLED: 'true',
    DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL: 'true',
  },
});

datadogContainer.addEnvironment(
  'DD_OTLP_CONFIG_RECEIVER_PROTOCOLS_HTTP_ENDPOINT',
  '0.0.0.0:4318',
);

// APM用ポートマッピング追加
datadogContainer.addPortMappings({
  containerPort: 4318,
  protocol: ecs.Protocol.TCP,
});

FireLens 日誌路由器設定

serviceTaskDefinition.addFirelensLogRouter('FirelensLogRouter', {
  image: ecs.ContainerImage.fromRegistry('amazon/aws-for-fluent-bit:stable'),
  essential: false,
  memoryReservationMiB: 50,
  firelensConfig: {
    type: ecs.FirelensLogRouterType.FLUENTBIT,
    options: {
      enableECSLogMetadata: true,
      configFileType: ecs.FirelensConfigFileType.FILE,
      configFileValue: '/fluent-bit/configs/parse-json.conf',
    },
  },
  logging: ecs.LogDriver.awsLogs({
    streamPrefix: 'firelens',
    logGroup: logGroup,
  }),
});

Next.js 方面的變化

加入dd-trace 。由於本專案使用 Bun,因此新增方式如下:

順便說一句,Bun 用途廣泛,強烈推薦。

% bun add dd-trace

由於我們使用了 App Router,因此在src/下建立 tracer.ts 並寫入以下程式碼。

import tracer from 'dd-trace';

tracer.init({
  logInjection: true,
  version: process.env.DD_VERSION,
  env: process.env.DD_ENV,
  service: process.env.DD_SERVICE,
});

export default tracer;

在與建立的檔案同級建立 instrumentation.ts 並從其中匯入。 instrumentation.ts 是在 Next.js 應用程式啟動時僅執行一次的文件,通常用於初始化測量和監控。

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('./tracer');
  }
}

透過這些設置,我能夠將日誌和 APM 從我的 Next.js 應用程式轉發到 Datadog。

9CE692B2-5EB6-4548-A06B-E4E02AE93BBC.jpeg

参考資料


原文出處:https://qiita.com/Syoitu/items/086f828cf7d8111f8a62


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
站長阿川

站長阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

站長精心設計,帶你實作 63 個小專案,得到作品集!

立即開始免費試讀!