기술나눔

Elasticsearch: Node.js ECS 로깅 - Winston

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

이것은 이전 기사의 연속입니다 "Elasticsearch: Node.js ECS 로깅 - Pino” 계속해서 이전 기사에서 Winston 패키지를 사용하여 대상을 지정하는 방법에 대해 설명했습니다. 노드.js 애플리케이션은 날짜에 맞게 ECS를 생성합니다.이 Node.js 패키지는윈스턴 로거포맷터가 제공됩니다. Elastic Common Schema(ECS) 로깅 호환 가능.결합하다파일비트 발신자님, Elastic Stack의 한 곳에서 모든 로그를 모니터링하실 수 있습니다. Winston 3.x 버전 >=3.3.3을 지원합니다.

설정

설치하다

  1. npm install @elastic/ecs-winston-format
  2. npm install winston

구성

윈스턴-로깅.js

  1. const winston = require('winston');
  2. const { ecsFormat } = require('@elastic/ecs-winston-format');
  3. const logger = winston.createLogger({
  4. format: ecsFormat(/* options */), // 1
  5. transports: [
  6. new winston.transports.Console()
  7. ]
  8. });
  9. logger.info('hi');
  10. logger.error('oops there is a problem', { err: new Error('boom') });
  • ECS 포맷터를 Winston에 전달합니다.

위 코드를 실행한 결과는 다음과 같습니다.

Filebeat 구성

파일비트 7.16+

파일비트.yml

  1. filebeat.inputs:
  2. - type: filestream # 1
  3. paths: /path/to/logs.json
  4. parsers:
  5. - ndjson:
  6. overwrite_keys: true # 2
  7. add_error_key: true # 3
  8. expand_keys: true # 4
  9. processors: // 5
  10. - add_host_metadata: ~
  11. - add_cloud_metadata: ~
  12. - add_docker_metadata: ~
  13. - add_kubernetes_metadata: ~
  1. 파일 스트림 입력을 사용하여 활성 로그 파일에서 행을 읽습니다.
  2. 충돌이 발생하면 디코딩된 JSON 객체의 값은 Filebeat가 일반적으로 추가하는 필드(유형, 소스, 오프셋 등)를 덮어씁니다.
  3. JSON 언마샬링 오류가 발생하면 Filebeat는 "error.message" 및 "error.type: json" 키를 추가합니다.
  4. Filebeat는 디코딩된 JSON에서 점 키를 반복적으로 제거하고 이를 계층적 객체 구조로 확장합니다.
  5. 프로세서는 데이터를 향상시킵니다.보다프로세서 자세히 알아보기

파일비트 < 7.16

파일비트.yml

  1. filebeat.inputs:
  2. - type: log
  3. paths: /path/to/logs.json
  4. json.keys_under_root: true
  5. json.overwrite_keys: true
  6. json.add_error_key: true
  7. json.expand_keys: true
  8. processors:
  9. - add_host_metadata: ~
  10. - add_cloud_metadata: ~
  11. - add_docker_metadata: ~
  12. - add_kubernetes_metadata: ~

자세한 내용은 다음을 참조하세요. 파일비트 참조

사용하는 방법

윈스턴-로깅.js

  1. const winston = require('winston');
  2. const { ecsFormat } = require('@elastic/ecs-winston-format');
  3. const logger = winston.createLogger({
  4. level: 'info',
  5. format: ecsFormat(/* options */), // 1
  6. transports: [
  7. new winston.transports.Console()
  8. ]
  9. });
  10. logger.info('hi');
  11. logger.error('oops there is a problem', { foo: 'bar' });
  1. 아래에서 사용 가능한 옵션을 확인하세요.
node winston-logging.js | jq .

이 스크립트를 실행하세요(다음 위치에서 사용 가능).여기획득)은 위와 유사한 로그 출력을 생성합니다.

포맷터는 데이터를 JSON으로 직렬화하는 역할을 담당하므로 추가할 필요가 없습니다. 제이슨 포맷터.또한 포맷터가 자동으로 타임스탬프를 생성하므로 추가할 필요가 없습니다.타임스탬프 포맷터.

오류 로깅

기본적으로 포맷터는 Error 인스턴스의 err 메타필드를 다음으로 변환합니다. ECSError 필드 .예를 들어

윈스턴-로깅.js

  1. const winston = require('winston');
  2. const { ecsFormat } = require('@elastic/ecs-winston-format');
  3. const logger = winston.createLogger({
  4. format: ecsFormat(),
  5. transports: [
  6. new winston.transports.Console()
  7. ]
  8. });
  9. const myErr = new Error('boom');
  10. logger.info('oops', { err: myErr });

err 메타필드의 특수 처리는 ConvertErr: false 옵션을 통해 비활성화할 수 있습니다.

윈스턴-로깅.js

  1. const winston = require('winston');
  2. const { ecsFormat } = require('@elastic/ecs-winston-format');
  3. const logger = winston.createLogger({
  4. format: ecsFormat({convertErr: false} ),
  5. transports: [
  6. new winston.transports.Console()
  7. ]
  8. });
  9. const myErr = new Error('boom');
  10. logger.info('oops', { err: myErr });

HTTP 요청 및 응답 로깅

ConvertReqRes: true 옵션을 사용하면 포맷터는 각각 req 및 res 메타필드로 전달될 때 Node.js 코어를 자동으로 변환합니다. 요구 그리고응답 물체.

윈스턴-로깅.js

  1. const http = require('http');
  2. const winston = require('winston');
  3. const { ecsFormat } = require('@elastic/ecs-winston-format');
  4. const logger = winston.createLogger({
  5. level: 'info',
  6. format: ecsFormat({ convertReqRes: true }), // 1
  7. transports: [
  8. new winston.transports.Console()
  9. ]
  10. });
  11. const server = http.createServer(handler);
  12. server.listen(3000, () => {
  13. logger.info('listening at http://localhost:3000')
  14. });
  15. function handler (req, res) {
  16. res.setHeader('Foo', 'Bar');
  17. res.end('ok');
  18. logger.info('handled request', { req, res }); // 2
  19. }
  1. ConvertReqRes 옵션 사용
  2. req 및/또는 res 메타필드 기록

이것은 다음을 사용합니다 ECS HTTP 필드 요청 및 응답 정보가 포함된 로그를 생성합니다.예를 들어

위에서 우리는 액세스해야합니다 http://로컬호스트:3000 그래야만 위에 표시된 날짜 정보를 볼 수 있습니다.

로그 상관 관계에 APM 사용

이것 ECS 로그 포맷터탄력적 APM 통합.Node 애플리케이션을 사용하는 경우Node.js Elastic APM 에이전트, APM 서비스 또는 추적 및 로그 데이터를 상호 연결하기 위해 여러 필드가 로그 레코드에 추가됩니다.

  • 현재 범위를 추적할 때 호출되는 로그 문(예: logger.info(...))에는 다음이 포함됩니다.추적 필드— trace.id、transaction.id、span.id。
  • APM 에이전트에 의해 결정되거나 구성된 여러 서비스 식별자 필드는 Kibana(service.name, service.version, service.environment, service.node.name)의 서비스와 로그 간의 교차 연결을 허용합니다.
  • event.dataset는 Elastic Observability 애플리케이션에서 활성화됩니다.로그율 이상 탐지

예를 들어 다음을 실행합니다. 예제/http-with-elastic-apm.js 그리고컬 -i 로컬호스트:3000/ 다음 내용을 포함하는 로그 레코드가 생성됩니다.

  1. % node examples/http-with-elastic-apm.js | jq .
  2. ...
  3. "service.name": "http-with-elastic-apm",
  4. "service.version": "1.4.0",
  5. "service.environment": "development",
  6. "event.dataset": "http-with-elastic-apm"
  7. "trace.id": "7fd75f0f33ff49aba85d060b46dcad7e",
  8. "transaction.id": "6c97c7c1b468fa05"
  9. }

이러한 ID는 APM 에이전트가 보고한 추적 데이터와 일치합니다.

Elastic APM과의 통합은 apmIntegration: false 옵션을 통해 명시적으로 비활성화할 수 있습니다. 예를 들면 다음과 같습니다.

  1. const logger = winston.createLogger({
  2. format: ecsFormat({ apmIntegration: false }),
  3. // ...
  4. })

제한 사항 및 참고 사항

ECS 로깅 사양 로그 레코드의 처음 세 필드는 @timestamp, log.level 및 message인 것이 좋습니다. 버전 1.5.0부터 이 포맷터는 이 권장 사항을 따르지 않습니다. 이는 가능하지만 각 로그 레코드에 대해 ecsFields에 새 객체를 생성해야 합니다. ecs-logging 필드의 순서는 가독성을 위한 것이며 상호 운용성에 영향을 주지 않는다는 점을 고려하여 성능을 우선시하기로 결정했습니다.

인용하다

ecsFormat([옵션])

  • 옵션 {type-object}는 다음 옵션을 지원합니다.
    • ConvertErr {type-boolean} 레코드의 err 필드를 ECS 오류 필드로 변환할지 여부입니다.기본값:진실.
    • ConvertReqRes {type-boolean} req 및 res HTTP 요청과 응답 필드를 ECS HTTP, User-Agent 및 URL 필드에 기록할지 여부입니다.기본값:거짓.
    • apmIntegration {type-boolean} APM 에이전트 통합 활성화 여부.기본값:진실.
    • serviceName {type-string} "service.name" 값입니다. 지정된 경우 활성 APM 에이전트의 모든 값을 재정의합니다.
    • serviceVersion {type-string} "service.version" 값입니다. 지정된 경우 활성 APM 에이전트의 모든 값을 재정의합니다.
    • serviceEnvironment {type-string} "service.environment" 값입니다. 지정된 경우 활성 APM 에이전트의 모든 값을 재정의합니다.
    • serviceNodeName {type-string} "service.node.name" 값입니다. 지정된 경우 활성 APM 에이전트의 모든 값을 덮어씁니다.
    • eventDataset {type-string} "event.dataset" 값입니다. 지정된 경우 ${serviceVersion} 사용의 기본값이 재정의됩니다.

ECS 로깅 형식을 생성하는 Winston용 포맷터를 만듭니다.이것은 치료입니다ecsFields([옵션]) 그리고ecsStringify([옵션]) 단일 형식. 다음 두 가지는 동일합니다.

  1. const { ecsFormat, ecsFields, ecsStringify } = require('@elastic/ecs-winston-format');
  2. const winston = require('winston');
  3. const logger = winston.createLogger({
  4. format: ecsFormat(/* options */),
  5. // ...
  6. });
  7. const logger = winston.createLogger({
  8. format: winston.format.combine(
  9. ecsFields(/* options */),
  10. ecsStringify()
  11. ),
  12. // ...
  13. });

ecsFields([옵션])

  • 옵션 {type-object}는 다음 옵션을 지원합니다.
    • ConvertErr {type-boolean} 레코드의 err 필드를 ECS 오류 필드로 변환할지 여부입니다.기본값:진실.
    • ConvertReqRes {type-boolean} req 및 res HTTP 요청과 응답 필드를 ECS HTTP, User-Agent 및 URL 필드에 기록할지 여부입니다.기본값:거짓.
    • apmIntegration {type-boolean} APM 에이전트 통합 활성화 여부.기본값:진실.
    • serviceName {type-string} "service.name" 값입니다. 지정된 경우 활성 APM 에이전트의 모든 값을 재정의합니다.
    • serviceVersion {type-string} "service.version" 값입니다. 지정된 경우 활성 APM 에이전트의 모든 값을 재정의합니다.
    • serviceEnvironment {type-string} "service.environment" 값입니다. 지정된 경우 활성 APM 에이전트의 모든 값을 재정의합니다.
    • serviceNodeName {type-string} "service.node.name" 값입니다. 지정된 경우 활성 APM 에이전트의 모든 값을 덮어씁니다.
    • eventDataset {type-string} "event.dataset" 값입니다. 지정된 경우 ${serviceVersion} 사용의 기본 설정이 재정의됩니다.

로깅 정보 객체의 필드를 ECS 로깅 형식으로 변환하는 Winston용 포맷터를 생성합니다.

ecsStringify([옵션])

로그 레코드를 JSON으로 문자열화/직렬화하기 위한 Winston용 포맷터를 만듭니다.

이는 logform.json()과 유사합니다. 둘 다 safe-stable-stringify 패키지를 사용하여 JSON을 생성합니다. 몇 가지 차이점:

  • 이 문자열 변환기는 ECS 필드가 아니기 때문에 레벨 필드 직렬화를 건너뜁니다.
  • Winston은 bigint를 문자열로 변환하는 대체 프로그램을 제공합니다. 그 이유는 JavaScript JSON 파서가 bigint를 구문 분석할 때 정밀도가 떨어지기 때문입니다. 반대 의견은 BigInt가 유형을 숫자 대신 문자열로 변경한다는 것입니다. 현재 이 문자열 변환기는 BitInt를 문자열로 변환하지 않습니다.