2010-05-28 4 views
15

가능한 경우 하나의 파일에 내 C++ 프로젝트에서 비동기 및 스레드 안전 로깅을 수행 할 방법을 찾고 있습니다. 나는 현재 cerrclog을 작업에 사용하고 있지만 동기 적이기 때문에 어떤 것이 기록 될 때마다 실행이 잠시 멈추는 경우가 있습니다. 상대적으로 그래픽이 많은 앱이므로 이런 종류의 작업은 매우 짜증납니다.비동기 스레드로부터 안전한 C++ 로깅

새 로거는 이러한 일시 중지를 제거하기 위해 비동기 I/O를 사용해야합니다. 머지 않아 기본 멀티 스레딩을 추가 할 예정이므로 스레드 안전성 또한 바람직 할 것입니다.

나는 하나의 파일 당 스레드 접근 방식을 고려했지만 로그 관리가 악몽처럼 보일 것으로 보였다. 어떤 제안?

답변

4

이것은 매우 유용하고 실용적입니다. 내가 어떻게 알아? 나는 마지막 일을 정확하게 기록했다. 불행히도 (우리를 위해), 그들은 이제 코드를 소유하고 있습니다. :-) 슬프게도, 그들은 그것을 사용하지 않습니다.

가까운 장래에 오픈 소스 버전을 작성하려고합니다. 그 동안, 나는 당신에게 몇 가지 힌트를 줄 수 있습니다.

  1. I/O 조정자는 실제로 함수 이름입니다. 로거가 cout/cin과 호환되도록 자신의 로깅 클래스에 맞게 구현할 수 있습니다.
  2. 조작자 함수는 조작을 토큰 화하여 대기열에 저장할 수 있습니다.
  3. 스레드가 대기열에서 차단되어 로그 덩어리가 날아갈 때까지 기다릴 수 있습니다. 그런 다음 문자열 연산을 처리하고 실제 로그를 생성합니다.

대기열을 사용하기 때문에 본질적으로 스레드와 호환됩니다. 그러나, 당신은 여전히 ​​주어진 로그가되도록 큐에 쓰는 것에 대해 뮤텍스와 유사한 보호를하고 싶습니다. < < "stuff"< < "more stuff"; type 연산은 line-atomic로 남아 있습니다.

재미있게 보내세요!

+0

뮤텍스가 없다면 이미 쓰려고하는 스레드가 잠금 해제 될 때까지 회전해야합니다. 어떻게 도움이됩니까? – Electro

+0

나는 확실히 스트림으로 객체의 변환을 지연시키지 않을 것이다. 그것을 다른 스레드에 넣는 것은 그것을 동기화해야한다는 것을 의미합니다. 그리고 그것은 지옥처럼 상처를 줄 것입니다. –

+0

@Electro - 회전하지 않고 차단합니다. 그러나 문자열 처리를 수행하지 않는다면 대기열을로드하는 데 아주 짧은 간격입니다. 문자열 처리는 로깅 스레드에 의해 수행됩니다. @Matthieu, 실시간으로 문자열 처리를하는 것은 큐를로드하는 동안 차단하는 뮤텍스보다 훨씬 많은 것을 아.니다. –

0

나는 적절한 접근 방식이 하나의 파일 당 하나의 파일이 아니라 하나의 파일 당 하나의 스레드라고 생각한다. 시스템에서 하나의 파일 (또는 일반적으로 자원)이 한 스레드에서만 액세스되는 경우 스레드 안전 프로그래밍이 훨씬 쉬워집니다.

Logger를 전용 스레드 (또는 파일마다 여러 가지를 로깅하는 경우 여러 스레드)로 만들고 다른 모든 스레드에서 로그에 쓰면 입력 대기열에 메시지가 배치됩니다. 이전의 메세지의 기입이 완료하면 (자), 적절한 Logger thread로 이동합니다. Logger가 이벤트를 읽는 동안 큐에 이벤트를 추가하지 못하도록하는 뮤텍스와 큐가 비어있을 때까지 기다리는 Logger에 대한 조건이 있습니다.

+0

잠금 해제 대기열이있는 뮤텍스를 사용하지 않고도 빠져 나갈 수 있습니다. 조건부 변수는 훨씬 더 다르다. 요금에 따라 잠을 자고 나중에 깨우기보다는 회전하는 것을 선호 할 수 있습니다. 유휴 코어가 있는지 여부에 따라 달라집니다 :) –

+0

바쁜 일정이 우리 시스템에서 대기하는 경우 워치 독이 전체 응용 프로그램을 죽일 것입니다. – Cubbi

1

로그 라이브러리 사용을 고려해 보셨습니까?

최근에 발견 된 몇 가지가 있는데, 나는 Pantheios을 발견했으며 실제로 매우 놀라운 것처럼 보입니다.

더 많은 프런트 엔드 로거이므로 어떤 시스템이 사용되는지 사용자 정의 할 수 있습니다. 예를 들어 ACE 또는 log4cxx과 상호 작용할 수 있으며 사용하고 구성하기가 쉽습니다. 가장 큰 장점은 형식 유지 연산자를 사용한다는 점입니다. 항상 훌륭한 연산자입니다.당신은 단지 베어 로깅 라이브러리하려면

:

  • ACE를
  • log4c *
  • Boost.Log

는이 :)

나는 그것의 있음을 유의 선택 C++에서 lock-free 큐를 구현할 수 있으며 로깅에 유용합니다.

+0

흠, 나는 그 중 하나를 가지고 싶지 않습니다.이전 두 가지는 과도한 것처럼 보였고 후자는 리뷰에서 많은 성능 문제가있었습니다. 이는 Boost 컬렉션에 추가하지 않은 이유 중 하나였습니다. – Electro

17

나는이 1 년 + 오래된 스레드를 발견했습니다. 어쩌면 제가 쓴 비동기 로거가 흥미로울 수 있습니다.

http://www.codeproject.com/KB/library/g2log.aspx

G2log가 느린 디스크 액세스하는 백그라운드 작업자에 로그 항목을 전달하기 위해 보호 메시지 큐를 사용합니다.

나는 LOG 호출의 평균 시간을 증가 시키지만 최악의 경우 시간은 줄 였지만 현재는 크로스 플랫폼이므로 보호 대기열을 사용하고 있습니다. Windows/Visual Studio 2010 및 Ubuntu 11.10/gcc4.6에서 테스트되었습니다.

퍼블릭 도메인으로 출시되었으므로 문자열없이 원하는대로 할 수 있습니다.

+0

로깅이 블로킹으로 이어지지 않아야하는 경우 (예 : 인쇄물이있는 경쟁 조건 디버깅 ... 헤이 작동하고 간단합니다!) 타임 스탬프가있는 토큰을 저장하는 스레드 로컬 메시지 대기열을 사용하는 것이 좋습니다 아마도 async IO로 직접 출력하는 것이 더 좋다.) 데이터가 필요하다면 나중에 출력을 정렬해야하며 일반 로깅에서는 다소 번거로울 수 있지만 가능한 가장 낮은 동기화 양인 nil이 있습니다. – Voo

+0

중요한 것은 스레드 안전성 및 최소 차단뿐 아니라 소프트웨어가 중단 될 경우 로그 항목이 파일에 있는지 확인하는 것입니다 (세그먼트 화 오류, 부동 소수점 오류 등). G2log는 신호 처리기를 사용하여 "치명적인 신호"의 경우 신호가 계속되기 전에 파일에 대기중인 항목을 플러시하고 (프로그램을 중단합니다) –

+0

@ KjellHedström -이 링크 http : // stackoverflow의 단계를 따르십시오. co.kr/help/user-merge를 사용하여 계정을 병합하십시오. – ChrisF

0

나는 동일한 문제가 있었으며 완벽한 해결책을 찾았다 고 생각합니다. loguru라고하는 단일 헤더 라이브러리를 알려 드리겠습니다. https://github.com/emilk/loguru

사용하기 쉽고, 이식성 있고 구성 가능한 매크로 기반이며 기본적으로 #include은 없습니다 (달콤한, 달콤한 컴파일 시간).

관련 문제