구조적 로깅과 기본 로깅의 장점


110

우리는 새로운 앱을 만들고 있으며 구조화 된 로깅을 포함하고 싶습니다. 이상적인 설정은 SerilogC # 코드 및 BunyanJS 와 같은 것 입니다 . 이것들은 피드에 들어가서 fluentd여러 가지로 나갈 수 elasticsearch + kibana있습니다. 나는 처음에 생각하고있었습니다 . 우리는 이미 MySQL 데이터베이스를 가지고 있기 때문에 단기적으로 Serilog + Bunyan 설정 및 개발자가 그것을 사용하는 데 더 관심이 있으며 유창하고 나머지를 가져 오는 데 약간의 시간이 더 걸리는 동안 MySQL에 로그인 할 수 있습니다.

그러나 경험이 풍부한 코더 중 하나는 다음과 같이 MySQL을 log.debug("Disk quota {0} exceeded by user {1}", quota, user);사용하여 log4netselect 문을 사용 하고 실행 하는 것을 선호합니다 .SELECT text FROM logs WHERE text LIKE "Disk quota";

즉, 로깅 시스템 유형을 선택할 때 어떤 접근 방식이 더 좋거나 어떤 것을 고려해야합니까?


수정 한 내용에 동의합니다. 나는 구조적 로깅과 기본 로깅의 이점과 차이점을 이해하려고 노력하면서 누군가에게 무언가를 증명하려고 노력하지 않습니다. 내 마음에 구조화는 특히 로그 소스와 데이터를 표시 할 수있는 방법에서 훨씬 더 많은 유연성을 제공합니다. 이해의 시점에서 기본 로깅 및 MySQL 검색이 구조적 로깅보다 나은 이유는 무엇인지 설명 할 수 없습니다.
DTI-Matt

2
@ DTI-Matt serilog의 구조적 로깅은 기본 로깅 일 뿐이며, 인쇄하는 개체 만 형식화합니다. ToString을 매우 쉽게 재정 의하여 직접 수행 할 수있는 작업입니다. 보다 중요한 측면은 로그 파일의 구성 및 관리이며, 문자열 형식을 다른 형식으로 형식화하는 방법이 아니라 다른 방법은 성능입니다. 개발자가 log4net (좋은 로깅 라이브러리)을 사용하고자한다면, serilog (멋지게 보이는)를 선택하는 것이 "문제를 찾는 해결책"중 하나입니다.
gbjbaanb

@ DTI-Matt serilog를 보면 log4net과 매우 비슷합니다. log4net은 구성에서 구조적 로그 작성을 처리합니다. 추가 정보를 구성하고 테이블에 쓸 수 있으므로 로그 메시지를 검색 할 필요가 없습니다. 또한 유창한 tipstuff.org/2014/05/…에
RubberChickenLeader

여기에 개념적 질문의 개념을 이해하지 못하는 바보가 있습니다. ETL 기능에 대한 핸들링을 시도 할 때 데이터베이스 응용 프로그램의 방향에 대해 묻습니다. 나는 당신의 질문이 도마에 있다고 가정합니다.
user3916597

2
@gbjbaanb Serilog는 이벤트를 텍스트로 렌더링 할 때 log4net과 같은 방식으로 작동하지만 구조화 된 형식을 사용하여 로그를 저장하는 경우 명명 된 속성을 전달 된 인수와 연결합니다 (즉, 정규식 등을 사용하지 않고 검색 / 필터링 지원). ) HTH!
Nicholas Blumhardt

답변:


140

추가적인 노력없이 텍스트 로그를 사용하여 에뮬레이션 할 수없는 구조화 된 접근 방식 에는 두 가지 근본적인 발전 이 있습니다.

이벤트 유형

log4net으로 두 가지 이벤트를 작성할 때 다음과 같이하십시오.

log.Debug("Disk quota {0} exceeded by user {1}", 100, "DTI-Matt");
log.Debug("Disk quota {0} exceeded by user {1}", 150, "nblumhardt");

이것들은 비슷한 텍스트를 생성합니다 :

Disk quota 100 exceeded by user DTI-Matt
Disk quota 150 exceeded by user nblumhardt

그러나 기계 가공에 관한 한, 두 줄의 다른 텍스트 일뿐입니다.

모든 "디스크 할당량 초과"이벤트를 찾을 수 있지만 다음 like 'Disk quota%'과 같이 다른 이벤트가 발생하면 이벤트를 찾는 단순한 경우 가 줄어 듭니다.

Disk quota 100 set for user DTI-Matt

텍스트 로깅은 처음에 이벤트 소스에 대한 정보를 버리고,보다 정교하게 일치하는 표현식으로 로그를 읽을 때 재구성해야합니다.

반대로, 다음 두 Serilog 이벤트 를 작성할 때 :

log.Debug("Disk quota {Quota} exceeded by user {Username}", 100, "DTI-Matt");
log.Debug("Disk quota {Quota} exceeded by user {Username}", 150, "nblumhardt");

이것들은 log4net 버전과 비슷한 텍스트 출력을 생성하지만 뒤에서 "Disk quota {Quota} exceeded by user {Username}" 메시지 템플릿 은 두 이벤트에 의해 전달됩니다.

적절한 싱크를 사용하면 나중에 쿼리를 작성 하고 디스크 할당량을 초과 한 이벤트를 정확하게where MessageTemplate = 'Disk quota {Quota} exceeded by user {Username}' 얻을 있습니다.

모든 로그 이벤트와 함께 전체 메시지 템플릿을 저장하는 것이 항상 편리한 것은 아니므로 일부 싱크는 메시지 템플릿을 숫자 EventType값 (예 0x1234abcd:)으로 해시하거나 로깅 파이프 라인에 기능을 추가하여 직접 수행 할 수 있습니다 .

아래의 다음 차이점보다 미묘하지만 큰 로그 볼륨을 처리 할 때 매우 강력합니다.

구조화 된 데이터

디스크 공간 사용에 대한 두 가지 이벤트를 다시 고려하면 텍스트 로그를 사용하여 특정 사용자를 쿼리하기에 충분히 쉽습니다 like 'Disk quota' and like 'DTI-Matt'.

그러나 생산 진단이 항상 간단한 것은 아닙니다. 디스크 할당량이 125MB 미만인 이벤트를 찾아야한다고 상상해보십시오.

Serilog를 사용하면 다음과 같은 변형을 사용하여 대부분의 싱크에서 가능합니다.

Quota < 125

정규식에서 이러한 종류의 쿼리를 구성하는 것이 가능하지만 빨리 지치게되고 일반적으로 최후의 수단이됩니다.

이제 여기에 이벤트 유형을 추가하십시오.

Quota < 125 and EventType = 0x1234abcd

여기서는 이러한 기능이 간단한 방식으로 결합되어 프로덕션 디버깅을 로그로 일류 개발 활동처럼 느끼게 만드는 방법을 알아보기 시작합니다.

사전 예방하기 쉽지 않은 또 다른 이점이 있지만 일단 정규 디버깅 해커의 땅에서 프로덕션 디버깅이 해제되면 개발자는 로그를 더 중요하게 생각하고 작성할 때 더 많은 관심과 고려를 기울입니다. 더 나은 로그-> 더 나은 품질의 응용 프로그램-> 더 많은 행복.


4
나는이 대답을 좋아한다. 아주 잘 쓰여져 있고 어떤 이유로 든 설명 할 수 없어서 자리에 앉게 해줍니다.
jokab

16

처리 할 로그를 수집 할 때 일부 데이터베이스로 구문 분석하거나 나중에 처리 된 로그를 검색하기 위해 구조화 된 로깅을 사용하면 일부 처리가보다 쉽고 효율적입니다. 파서는 알려진 구조 ( 예 : JSON, XML, ASN.1 등)를 활용하고 정규식 (컴파일 및 실행에 상대적으로 비용이 많이들 수 있음)과 달리 구문 분석에 상태 머신을 사용할 수 있습니다. 같은 당신의 동료에 의해 제안 된 것과 같은, 자유 형식 텍스트의 구문 분석, 정규 표현식에 의존하는 경향이 그 텍스트에 의존 변경하지 . 이렇게하면 자유 형식의 텍스트 구문 분석이 다소 약해집니다 ( 즉, 구문 분석은 코드의 정확한 텍스트에 밀접하게 연결됩니다).

검색 / 조회 사례도 고려하십시오 ( :

SELECT text FROM logs WHERE text LIKE "Disk quota";

LIKE조건은 모든 text행 값 과 비교해야 합니다. 다시 말하지만, 이것은 특히 계산이 비싸며 특히 와일드 카드를 사용할 때 더 그렇습니다 .

SELECT text FROM logs WHERE text LIKE "Disk %";

구조화 된 로깅을 사용하면 디스크 오류 관련 로그 메시지가 JSON에서 다음과 같이 보일 수 있습니다.

{ "level": "DEBUG", "user": "username", "error_type": "disk", "text": "Disk quota ... exceeded by user ..." }

이러한 종류의 구조의 필드는 들어 SQL 테이블 열 이름에 매우 쉽게 매핑 될 수 있습니다. 이는 조회가보다 구체적 / 세분화 될 수 있음을 의미합니다.

SELECT user, text FROM logs WHERE error_type = "disk";

해당 열 값에 절을 사용하지 않는 한LIKE 자주 검색 / 조회 할 것으로 예상되는 값이있는 열에 인덱스를 배치 할 수 있습니다 . 로그 메시지를 특정 범주로 세분화할수록 조회 대상을 더 많이 지정할 수 있습니다. 예를 들어, error_type위의 예에서 필드 / 열에 더하여 또는 그와 같이 만들 수도 있습니다 "error_category": "disk", "error_type": "quota".

로그 메시지에 당신이 더 많은 구조는 (같은 더 구문 분석 / 검색 시스템 fluentd, elasticsearch, kibana) 그 구조를 활용하고, 더 빠른 속도와 더 적은 CPU / 메모리 자신의 작업을 수행 할 수 있습니다.

도움이 되었기를 바랍니다!


1
+1 속도와 효율성 만이 아니라고 덧붙이고 싶습니다. 구조화 된 로깅과 "구조화 된 쿼리"를 사용할 때 검색 결과의 관련성이 훨씬 높아집니다. 다른 문맥에서 발생하는 단어를 검색하지 않으면 수많은 관련성이없는 결과가 나옵니다.
Marjan Venema

1
나 에게서도 +1, 나는 이것이 손톱이라고 생각합니다. 이벤트 유형의 경우에도 확장하기 위해 아래에 약간 다른 공식을 추가했습니다.
Nicholas Blumhardt

8

앱이 하루에 수백 개의 로그 메시지를 생성 할 때 구조화 된 로깅의 이점은 그리 크지 않습니다. 배포 된 여러 다른 앱에서 초당 수백 개의 로그 메시지가 표시 될 때 확실히 그렇습니다.

관련하여, 로그 메시지 가 ELK 스택으로 끝나는 설정 은 SQL에 로깅하는 데 병목 현상이 발생하는 규모에도 적합합니다.

SQL을 사용 select .. like하여 "기본 로깅 및 검색"설정을 보았고 정규 표현식이 한계에 도달했습니다. 거짓 긍정, 누락, 유지하기 어려운 knwon 버그가있는 끔찍한 필터 코드가 있으며 누구도 만지고 싶어하지 않습니다. 필터의 가정을 따르지 않는 새로운 로그 메시지, 보고서에서 로그를 작성하지 않도록 코드에서 로깅 문을 건드리지 않음 등

따라서이 문제를 더 잘 처리하기 위해 여러 소프트웨어 패키지가 등장하고 있습니다. Serilog가 있습니다. NLog 팀이보고 있다고 들었습니다. Nlog를 StructuredLogging.Json위해 썼습니다. 또한 새로운 ASP.Net 코어 로깅 추상화가 "로깅 공급자가 구조화 된 로깅을 구현할 수있게 해줍니다"라는 것을 알았 습니다.

StructuredLogging의 예입니다. 다음과 같이 NLog 로거에 로그인하십시오.

logger.ExtendedError("Order send failed", new { OrderId = 1234, RestaurantId = 4567 } );

이 구조화 된 데이터는 키바 나로갑니다. 값 1234OrderId로그 항목 의 필드에 저장됩니다 . 그런 다음 kibana 쿼리 구문을 사용하여 모든 로그 항목을 검색 할 수 있습니다 @LogType:nlog AND Level:Error AND OrderId:1234.

Message그리고 OrderId당신이 필요로하는 정확한 혹은 부정확 한 일치 검색, 또는 개수에 대한 집계 할 수 있습니다 지금 바로 필드는 다음과 같습니다. 강력하고 유연합니다.

로부터 StructuredLogging 모범 사례 :

기록 된 메시지는 매번 동일해야합니다. ID 또는 수량과 같은 데이터 값을 포함하도록 형식화 된 문자열이 아니라 상수 문자열이어야합니다. 그러면 쉽게 검색 할 수 있습니다.

기록 된 메시지는 고유해야합니다. 즉, 관련되지 않은 로그 문으로 생성 된 메시지와 동일하지 않아야합니다. 그런 다음 검색하면 관련이없는 것들과 일치하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.