Lambda Functionを定義するとLogGroupが自動で作成される仕組みをCDKで作ってみた

2019.09.07

こんにちは、CX事業本部の夏目です。

最近、クラスメソッド社内でCDKが流行っているようなので自分ものっかろうと思います。

ということで今回は、Lambda Functionを定義すると自動でLogGroupが作られる仕組みを作ってみようと思います。
(CDKは色々な言語で書けますがここではTypeScriptを使用します)

Stackのリソース一覧を取得する

自動でLogGroupを作成するには、まずスタックのリソース一覧を取得する必要があります。

Resourceを記述する Stack クラスには次のプロパティがあります。

node
Type: ConstructNode
Construct tree node which offers APIs for interacting with the construct tree.
https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.Stack.html#node

Construct treeとありますし、CDKで定義するリソースのクラスは IConstructを実装しているので、ここに情報が入ってそうです。

ConstrunctNode を見てみると次のプロパティがあります。

children
Type: Array<IConstruct>
All direct children of this construct.
https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.ConstructNode.html#children

All direct childrenとありますし、どうやらこれが定義したリソースの一覧のようです。

Lambda定義を元にLogGroupを自動生成してみる

import cdk = require('@aws-cdk/core');
import * as lambda from "@aws-cdk/aws-lambda";
import {Duration} from "@aws-cdk/core";
import {LogGroup} from "@aws-cdk/aws-logs";
import {Topic} from "@aws-cdk/aws-sns";

// Lambdaの定義は別のクラスとして行う
class TmpAutoLogGroupStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const lambdaProps: lambda.FunctionProps = {
      code: lambda.Code.fromAsset('src'),
      handler: 'index.handler',
      runtime: lambda.Runtime.PYTHON_3_6,
      timeout: Duration.seconds(30)
    };

    // 試しに2つ同じ実体を持つLambdaを定義
    new lambda.Function(this, 'HelloFunction01', lambdaProps);
    new lambda.Function(this, 'HelloFunction02', lambdaProps);

    // Lambda以外のリソースも定義
    new Topic(this, 'TmpTopic');
  }
}

// Lambdaを定義したクラスを継承して、LogGroupの生成を行う
export class AutoLogGroupStack extends TmpAutoLogGroupStack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    // 継承元のLambda定義を行う
    super(scope, id, props);

    for (const resource of this.node.children) {
      // Lambdaの定義だけを抽出
      if (resource instanceof lambda.Function) {
        new LogGroup(this, `${resource.node.id}LogGroup`, {
          logGroupName: `/aws/lambda/${resource.functionName}`
        });
      }
    }
  }
}

Stackの中身を確認してから、LogGroupを生成するのでLambdaを定義するクラスを継承して、LogGroupを生成させています。

これをデプロイしてみます。

無事LogGroupも生成されました。

まとめ

Lambda Functionが含まれると自動的にLogGroupを作成することができました。 これをどうすれば、効率的使えるようにできるのかが今後の課題です。