Lambda의 기본 로그를 출력하지 않고 의도한 로그만 출력

10768 단어 람다CloudWatchAWS
Lambda 실행 시 기본적으로 표시되는 로그를 숨기면서 애플리케이션에서 의도한 로그만 CloudWatch Logs에 출력하는 방법입니다.

CloudWatch Logs 요금이 높기 때문에 가능한 한 저장하는 로그를 줄이고자 하는 목적으로 대응했습니다.

일반 로그 출력 (아무것도하지 않는 경우)



우선은 아무것도 하지 않는 경우입니다.

이번 테스트에서 이용하는 Lambda입니다.
Node.js 12.X입니다.

람다
exports.handler = async (event) => {
    console.log('log test');
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

출력되는 로그는 다음과 같습니다.
START RequestId: XXXXXX Version: $LATEST
2020-03-13T13:33:26.678Z    XXXXXX  INFO    log test
END RequestId:  XXXXXX 
REPORT RequestId:  XXXXXX   Duration: 17.18 ms  Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 70 MB  Init Duration: 108.39 ms    

이와 같이 Lambda상에서 출력하도록(듯이) 쓴 것은, log test 뿐입니다만, START~ END~ REPORT~ 라고 하는 Lambda가 디폴트로 출력하는 로그가 함께 출력되고 있습니다.
이번 기사는, 이러한 디폴트의 로그는 출력하지 않게 하면서, Lambda로 쓴 메세지만을 출력하고 싶다고 하는 내용입니다.

기본 로그를 출력하지 않기



IAM 권한 수정



Lambda의 기본 로그를 출력하지 않으려면 IAM을 수정하십시오.

Lambda를 만들 때 역할을 동시에 만들면 해당 역할에 CloudWatch log 서비스에 대한 쓰기 권한이 있습니다.

또한 CloudWatch 로그의 CreateLogStream, PutLogEvents 작업에 대한 쓰기 권한이 설정되어 있습니다.

이 중 CreateLogStream 의 기입 허가를 제외하는 것으로, 자동적으로 로그 스트림이 작성되지 않기 때문에, 결과적으로 로그를 출력하지 않게 설정할 수 있습니다.






상기는 CreateLogStream 의 허가를 제외하고 PutLogEvents 만이 남아 있는 상태입니다.

다만 이 대응을 실시하면(자) console.log 도 출력되지 않게 됩니다.

스트림 만들기


CreateLogStream 권한을 제거하면 로그 스트림이 자동으로 생성되지 않습니다.
따라서 로그 스트림을 수동으로 만듭니다.

CloudWatch 로그 그룹에서 로그 스트림을 생성합니다.












수동으로 로그 출력



그럼 나머지는 로그를 출력하는 처리를 써 갑니다.

로그 출력은 aws-sdk를 사용합니다.
그럼 전체적인 코드를 보여드리겠습니다.

로그 출력 Lambda
const LOG_GROUP_NAME = '/aws/lambda/loglog';
const LOG_STREAM_NAME = 'test';

const AWS = require('aws-sdk');
const cloudwatchlogs = new AWS.CloudWatchLogs({region: 'ap-northeast-1'});

const outLog = async (msg) => {
  const describeParams = {
    logGroupName: LOG_GROUP_NAME,
    logStreamNamePrefix: LOG_STREAM_NAME,
  };
  const data = await cloudwatchlogs.describeLogStreams(describeParams).promise();
  console.log(data);
  let sequenceToken = null;
  if (data.logStreams[0]) {
    sequenceToken = data.logStreams[0].uploadSequenceToken;
  }
  console.log('sequenceToken:' + sequenceToken);

  const params = {
    logEvents: [{
      message: msg,
      timestamp: Date.now()
    }],
    logGroupName: LOG_GROUP_NAME,
    logStreamName: LOG_STREAM_NAME,
    sequenceToken: sequenceToken,
  };
  console.log('put start');
  await cloudwatchlogs.putLogEvents(params).promise();
  console.log('put end');
};

exports.handler = async (event) => {

    await outLog('log test');
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

해설



로그의 출력은 putLogEvents 메소드를 이용합니다. putLogEvents AWS 문서

입력 매개변수는 로그를 출력하기 위한 로그 그룹, 로그 스트림, 출력할 메시지 등을 지정합니다.

PutLogEvents를 두 번 이상 호출하면 sequenceToken을 부여하지 않으면 거부됩니다.
그 때문에, describeLogStreams 메소드를 이용해, uploadSequenceToken 를 취득해, 그 값을 PutLogEvents 에 건네주고 있습니다.
describeLogStreams AWS 문서

이번 outLog 라는 function을 작성했습니다만, 어느 Lambda에서도 사용한다고 하면, Lambda-Layer로 해 버리는 것도 좋다고 생각합니다.

기타



이번 대응에서는 CreateLogStream를 거부했습니다만, CreateLogStream는 허가로 하면서,PutLogEvents 에서 허가하는 자원을 일부에 한정(예를 들면 고정치+날짜등)으로 하는 것으로, Lambda로 로그 스트림의 작성+작성한 로그 스트림에 로그 출력등의 대응도 문제 없습니다.
그 쪽이 로그가 정리되어 출력 가능하므로 더 좋다고 생각합니다.

좋은 웹페이지 즐겨찾기