코드사이트 로깅 실전 활용 기법 (Real-world CodeSite Logging Techniques) 를 요약했습니다. (이 요약 번역은 원본 비디오와 내용이 일부 다르거나, Q&A등 일부 생략되었을 수 있습니다.)

 

실전에서 바로 활용할 수 있도록 코드사이트(CodeSite)의 로깅 기술 중 핵심적인 것을 뽑아서 설명합니다. (코드사이트 무료 에디션은 델파이의 겟잇 패키지 매니저에서 무료로 받을 수 있습니다.)

  •  코드사이트(CodeSite) 개요: Raize에서 만든 로깅 도구 개요
  • (데모) 겟잇에서 코드 사이트 익스프레스 무료 다운로드
  • CodeSite 도구들  
  • (데모) CodeSite 도구 메뉴 위치 
  • (데모) CodeSite 폴더 살펴보기
  • (데모) CSDispatcher.exe를 윈도우 서비스로 설치하기 (07분07초부터)
  • (데모) CSContoller.exe를 통해 디스패처를 수작업으로 시작/종료하거나 설정하기 (07분29초부터)
  • (데모) 고객용 샘플앱을 통해 로깅 살펴보기 (08분26초부터)
  • (데모) Method Tracer 사용하여 오류 위치를 쉽게 찾기 (11분22초부터)
  • 디스패처 (CodeSite Dispatcher)
  • (데모) 원격 로깅 설정 (15분46초부터)
  • CodeSite.Send 메소드의 메시지 유형 
  • (데모) CodeSite.Send 메소드의 메시지 유형 활용하기 (19분09초부터)
  • (데모) 너무 큰 데이터세트가 로깅되는 것을 방지하기 (22분58초부터)
  • 스크래치패드 (CodeSite ScratchPad)
  • (데모) CodeSite ScratchPad에서 메모리 누수 파악하기 (24분54초부터)
  • CodeSite 로그 목적지 지정
  • (데모) DestinationString 직접 작성하기 (29분40초부터)
  • (데모) DestinationStringBuilder 사용하기 (34분25초부터)
  • CodeSite에서 Logger 여러개 사용하기
  • (데모) 하나의 앱에 CodeSite 로거 2개를 사용하기 (38분40초부터)
  • CodeSite 로거 활성화를 활용한 실전 팁
  • (데모) 평소에는 오류 정보만 로깅하다가 꼭 필요할 때에 전체 로깅하기 (45분05초부터)
  • CodeSite의 OnSendMsg로 메시지 가로채기와 다루기
  • (데모) OnSendMsg로 메시지 가로채기와 다루기 (49분19초부터)
  • 세션에서 소개한 코드사이트 로깅 테크닉 요약

발표자 (Bob Swart)는 Dr. Bob으로 잘 알려진 델파이 개발자이자 컨설선트입니다. 

  • Dr. Bob의블로그: drbob42.com 

원본 비디오 시청: https://delphicon.embarcadero.com/talks/real-world-codesite-logging-techniques-1/

 

코드사이트(CodeSite) 개요: Raize의 로깅 도구 개요

- 에디션

    - 코드사이트 익스프레스: 무료, 겟잇패키지매니저에서 다운로드

    - 코드사이트 스튜디오: 유료, www.raize.com에서 구입

- 로그 표현 방식

    - 라이브 로깅

    - 파일 로깅

- 로그 저장 위치

    - 로컬 로깅

    - 원격 로깅 (스튜디오 에디션 Only, 배포한 앱에서 로그를 원격의 로그 저장소로 보내도록 함)

- 로깅 솔루션으로서 제공되는 기능

    - 앱 사용자는 어떤 로그가 얼마나 수집되는 지를 신경쓰지 않아도 됨

    - 로그 파일 분석 도구 제공됨

 

(데모) 겟잇에서 (무료 에디션인) 코드 사이트 익스프레스 무료 다운로드

Delphi > Tools > GetIt Package Manager 선택 > 겟잇 필터에서 ‘Code’라고 입력 > CodeSite Express를 선택하고 [Install] 버튼 클릭 후 기본 설정을 따라 설치 > 델파이 재시작 후 겟잇에서 Installed로 표시되는 지 확인

 

DelphiCon-CodeSite1-GetIt.png

(그림1. 겟잇에서 CodeSite를 찾아서 설치하기)

 

CodeSite 도구들

- 로깅 도구

    - CSDispatcher.exe: 앱에서 발생한 로그를 가져와서 저장하는 도구 (윈도우 서비스로 작동하면 자동으로 시작/종료되므로 편함)

    - CSContoller.exe: CSDispatcher를 시작/종료 하거나 설정하는 도구

- 조회 도구

    - CSFileViewer.exe: 파일로 저장된 로그를 조회하는 도구

    - CSLiveViewer.exe: 로그가 전달되면 바로 보여주는 도구 (매우 유용함)

- 기타 도구

    - CSDestStringBuilder.exe: 로그 저장소 설정을 선택하면 해당 문자열이 생성됨

    - CSFileExporter.exe: 로그 파일을 XML형식으로 내보내기

    - CSFileSplitter.exe: 큰 로그 파일을 지정된 파일 크기의 작은 로그 파일들로 쪼개기

    - CSMergeFiles.exe: 작은 로그 파일들을 하나로 병합하기

 

(데모) CodeSite 도구들

- Delphi > Tools > CodeSite > 하위 메뉴로 각 도구들이 표시됨 

- (예를 들어) Delphi > Tools > CodeSite > CodeSite Method Tracer를 사용하면,
   메소드 진입과 메소트 통과를 로깅하도록 하는 코드를 쉽게 추가할 수 있음

 

(데모) CodeSite 폴더 살펴보기

코드사이트 폴더 (기본 위치는 Program Files (x86) > Raize > CS5

- Bin 폴더: 설치된 앱이 있는 곳으로서 CodeSite의 모든 도구들의 실행 파일이 있는 곳

- Tool 폴더: CS5_Tools.exe가 있는 곳 

    - CS5_Tools.exe를 사용하면, 고객의 컴퓨터에도 디스패처, 뷰어 등의 도구를 설치할 수 있다.

    - 내 경우 고객의 컴퓨터에는 로컬 로깅일 경우 대체로 ‘디스패처’만 설치한다. 디스패처는 ‘윈도우 서비스’로 작동하도록 설치하여서 고객이 로그와 관련하여 크게 신경쓰지 않도록 한다. (원격 로깅의 경우에는 고객의 컴퓨터에 디스패처도 설치할 필요가 없다)

 

(데모) CSDispatcher.exe를 윈도우 서비스로 설치하기 (7분7초부터)

- 명령창 C:\Program Files (x86)\Raize\CS5\Bin 위치에서 CSDispatcher.exe / install 을 입력하고 엔터키를 치면, Service installed successfully 메시지 창이 표시됨


- C:\Program Files (x86)\Raize\CS5\Bin>CSDispatcher.exe / install

- 위와 같이 설치하면, 로그를 수작업으로 시작하거나 종료할 필요가 없음


 

(데모) CSContoller.exe를 통해 디스패처를 수작업으로 시작/종료하거나 설정하기 (7분29초부터)

- 이미 디스패처가 윈도우 서비스로 설치되었다면 제거한다.

- CSContoller.exe를 관리자 계정으로 실행 (Run as Administrator)

 

(데모) 고객용 샘플앱을 통해 로깅 살펴보기 (8분26초부터)

아래와 같이 로깅 코드를 넣으면, 코드사이트로 SQL 구문이 오류 정보와 함께 전달되므로, SQL 구문으로 인해 발생된 오류임음을 쉽게 파악할 수 있음

uses

  CodeSiteLogging;

procedure …

begin

  FDQuery1.Close;

  FDQuery1.SQL.Text := ‘SELECT * FROM Customers’+

    ‘WHERE Country = ‘’’+ cbCountry.Items[cbCountry.ItemIndex] + ‘’’’;

  try

    FDQuery1.Open;

  except

    on E: Exception do

      CodeSite.SendException(FDQuery1.SQL.Text, E)

  end;

end;

 

(데모) Method Tracer 사용하여 오류 위치를 쉽게 찾기 (11분22초부터)

- 원하는 메소드를 선택하고 Trace Method, $IFDEF 등을 지정하면 해당 위치에 로깅 코드가 들어간다.

- $IFDEF는 DEBUG가 기본 설정이지만, 원한다면 RELEASE 등을 설정할 수도 있다.

DelphiCon-CodeSite2-MethodTracer.png

(그림2. 특정 메소드 내 오류 발생 유무를 한눈에 파악할 수 있어서 오류가 난 지점을 쉽게 파악할 수 있다.)

 

디스패처 (CodeSite Dispatcher)

- 얼마든지 무료로 배포할 수 있다.

    - CS5_Tools.exe: 고객 컴퓨터에 로컬 로깅 (로컬에 로그를 남김)을 하기 위해 디스패처 등을 설치할 사용

    - 윈도우 서비스로 설치: CSDispatcher.exe / install

    - ConnectUsingTCP 옵션: 일반적인 로컬 로깅이 안될 때 또는 원격로깅을 할 때 선택

        - ISAPI DLL들이 포함되어서 서비스로 작동

        - 기본 포트: TCP 3434 또는 UDP 3435

    - 원격 로깅 시에는, ConnectUsingTCP(디스패처가 작동하는 원격 IP주소)

        - 고객의 컴퓨터에 디스패처를 설치할 필요없음

        - 고객의 앱에 코드사이트 로깅 코드가 들어 있기만 하면 됨

 

(데모) 원격 로깅 설정 (15분46초부터)

프로젝트 파일에서 Application.Initialize 아래에 코드 2줄을 추가한다.

 

program…

uses

  CodeSiteLogging,

..

begin

  Application.Initialize;

 

  CodeSite.Enabled := True;

  CodeSite.ConnectUsingTcp(192.168.1.19’);

  …

end.

 

그 결과

- 원격의 로그 서버에서 해당 로그를 볼 수 있다. 

- 고객 컴퓨터는 코드에서 지정된 대로 로그를 보내기만 하므로 아무것도 설치할 필요가 없다.

- 로그 서버를 별로로 두고, 각 고객의 컴퓨터에서 보내온 로그를 각 컴퓨터 별로 관리하면, 로그 파악을 위해 고객과 연락할 필요가 없다. 

 

CodeSite.Send 메소드의 메시지 유형

- csmYellow, csmGreen, csmOrange, csmBlue, csmRed,…

    - 각 색상별로 특정 유형이 지정되도록 하면 (특히 팀 프로젝트에서) 매우 유용하다.

    - 예시: 녹색(SQL문장), 노랑(결과), 파랑(SOAP 또는 REST 호출), 주황(XML 또는 JSON), 빨강(200 OK가 아닌 모든 Response) …

- csmInfo, csmWarning, csmError

- csmDataSet (CodeSiteDBTools 유닛 사용 시)

 

(데모) CodeSite.Send 메소드의 메시지 유형 활용하기 (19분09초부터)

uses

  CodeSiteLogging;

  CodeSiteDBTools; //csmDataSet 사용을 위함

procedure …

begin

  {$IFDEF DEBUG}CodeSite.TraceMethod(Self, ‘Button1Click’);{$ENDIF}

  FDQuery1.Close;

  FDQuery1.SQL.Text := ‘SELECT * FROM Customers’+

    ‘WHERE Country = ‘’’+ cbCountry.Items[cbCountry.ItemIndex] + ‘’’’;

  try

    // SQL 구문에는 녹색 표시 (그림3)

    CodeSite.Send(scmGreen, FDQuery1.SQL.Text);

    FDQuery1.Open;

 

    // 결과 데이터의 갯수에는 노랑색 표시 (그림3)

    CodeSite.Send(scmYellow, FDQuery1.RecordCount.ToString + ‘ 개 데이터’);

 

    // 결과 데이터세트를 통채로 전달 (그림4)

    CodeSite.Send(csmDataSet, ‘Customers’, FDQuery1);

  except

    on E: Exception do

      CodeSite.SendException(FDQuery1.SQL.Text, E)

  end;

end;

 

DelphiCon-CodeSite3-SendMsgTypes.png

(그림3. 녹색에는 SQL 구문이, 노랑색에는 해당 결과 데이터의 갯수가 표시된다. 그리고 로그 2개를 선택하면 좌측 하단에 두 로그 간의 시간 차이가 표시되므로, 수행 시간도 파악할 수 있다.)

 

DelphiCon-CodeSite4-csmDataSet.png

(그림4. csmDataSet을 사용하면 결과 데이터세트를 볼 수 있다. 주의! 너무 큰 데이터세트를 로그로 받지 않도록 하자)

 

(데모) 너무 큰 데이터세트가 로깅되는 것을 방지하기 (22분58초부터)

// (변경전)

CodeSite.Send(csmDataSet, ‘Customers’, FDQuery1);

 

// (변경후, 그림5)

If FDQuery1.RecordCount > 5 then

  CodeSite.SendWarning(‘데이터가 5개를 넘음’)

else

  CodeSite.Send(csmDataSet, ‘Customers’, FDQuery1);

 

DelphiCon-CodeSite5-csmDataSet2.png

(그림5. 결과 데이터가 5개 초과이므로 데이터는 남기지 않고, 지정된 메시지만 남긴다. 이 때 SendWarning 메소드를 사용했으므로, 해당 메시지에 느낌표 표시가 붙는다.)

 

스크래치패드 (CodeSite ScratchPad)

- (유료인) 스튜디오 에디션에 있는 기능

- 라이브 뷰어에 지정한 정보가 지정된 주기에 따라 실시간 표시되며 로그 파일로 남지는 않는다.

- 메모리 점유, 사용자 수 등 원하는 모든 문자열 정보를 실시간으로 볼 수 있다.

 

(데모) CodeSite ScratchPad에서 메모리 누수 파악하기 (24분54초부터)

procedure …

var

  S: TStringList;

begin

  S:= TStringList.Create;

  S.LoadFromFile(‘C:\temp\verybigfile.txt’);

  // Free 하지 않았으므로 한번 실행될 때 마다 16.6MB 메모리 누수가 발생한다.

end;

 

// [메모리 누수를 라이브 뷰어에 보내는 코드]

// 먼저 Timer 콘트롤을 추가하고 Interval을 2초로 주고 Timer 메소드에 아래 코드를 쓴다.

procedure TFrom42.Timer1Timer(Sender: Object);

begin

  CodeSite.Send(csmScratchPad, TimeToStr(now) + ‘ 메모리 사용: ‘ +

    (CurrentProcessMemory div (1024 * 1024).ToString + ‘ MB’); //CurrentProcessMemory 함수 설명은 생략

end;

 

고객의 컴퓨터의 (메모리 등) 자원 현황을 실시간으로 파악하고 재부팅 등 필요한 결정을 할 수 있다.

DelphiCon-CodeSite6-csmScratchPad.png

(그림6. 라이브뷰어의 스크래치패드 창을 열면 코드에 적힌 대로 현재 메모리 사용량이 표시된다.)

 

CodeSite 로그 목적지 지정

- 뷰어

    - Enabled 여부만 지정하면 됨

- 로그 파일

    - 모든 에디션: FilePath, FileName, MaxSize, MaxParts

    - 스튜디오 에디션에만: LogByDate, LogByDateFormat, Compressed

- DestinationStringBuilder: 설정을 하나의 문자열로 생성

 

(데모) DestinationString 직접 작성하기 (29분40초부터)

(프로젝트 파일에서)

 

program…

uses

  CodeSiteLogging,

..

 

var

  Destination: TCodeSiteDestination;

begin

  Application.Initialize;

 

  Destination := TCodeSiteDestination.Create(CodeSite);

  

  with Destination.LogFile do

  begin

    FilePath := ‘c:\tmp’; // C드라이브 경로에 로그 파일이 생성

    FileName := ‘DelphiCon2020.csl’;

    SetLogbyDate(True); // 일별로 로그 파일이 생성

    MaxSize := 2000;

    MaxParts := 1000;

    Active := True;

  end;

 

  Destination.Viewer.Active := False; // 라이브뷰어는 일단 끈다.

  CodeSite.Destination := Destination;

 

  CodeSite.Enabled := True;  // 로깅은 작동하도록 켠다

  CodeSite.ConnectUsingTcp(192.168.1.19’); //원격 장비로 셋팅되었으므로, 원격의 C드라이브에 로그 파일이 생성됨

 

 CodeSite.Send(‘델파이콘 2020 앱이 로딩됨’); //앱이 로딩되었음을 로그로 남긴다.

  …

end.

 

DelphiCon-CodeSite7-FileViewer.png

 

(그림7. 로그 파일을 클릭하면 파일 뷰어가 실행되며 로그를 볼 수 있다. 파일 뷰어는 라이브뷰어와 보는 방식이 같지만 스크래치패드가 없다는 점이 다르다) 

- 로그 파일이 클라이언트인 로컬 장비에 저장되는 것이아니라 원격 로그 서버에 저장되도록 하면 로그 관리가 중앙화되고 더 유용하다.

 

(데모) DestinationStringBuilder 사용하기 (34분25초부터)

DestinationStringBuilder를 통해 생성된 문자열을 넣으면 수작업으로 설정 코드를 넣을 필요가 없다.

DelphiCon-CodeSite8-DestinationStringBuilder.png

(그림8. DestinationStringBuilder를 통해 원하는 설정이 모두 담긴 문자열 하나를 만들 수 있다)

HTTP로 연결할 수도 있지만, TCP 포트가 허용된다면 굳이 HTTP로 웹서버에 연결할 필요까지는 없다.

 

// (변경 전)

with Destination.LogFile do

  begin

    FilePath := ‘c:\tmp’; // C드라이브 경로에 로그 파일이 생성

    FileName := ‘DelphiCon2020.csl’;

    SetLogbyDate(True); // 일별로 로그 파일이 생성

    MaxSize := 2000;

    MaxParts := 1000;

    Active := True;

  end;

 

// (변경 후)

 Destination.AsString := ‘[생성된 문자열을 여기에 붙여넣는다]’;

 

CodeSite에서 Logger 여러개 사용하기

- 여러 로거를 사용할 수 있다

    - 예: CodeSiteEx를 만들어서 에러와 익셉션인 경우에만 로그를 남기는 역할을 맡긴다 (데모 참조)

- 각 로거 별로 TCodeSiteDestination을 이용하여 로그 위치를 분리할 수 있다.

    - Errors.csl로 남기거나,

    - 라이브뷰어 (예: “알람 설정, 스크래치패드와 함께 사용)에 남기거나, 등

 

(데모) 하나의 앱에 CodeSite 로거 2개를 사용하기 (38분40초부터)

// [CodeSiteEX]라는 로거를 폼 변수로 하나 만들고, 이것을 Except 구문 안에서 사용하기 

// 1/2 폼 코드에서 

var 

  CodeSiteEx: TCodeSiteLogger; // 폼의 변수로 로거를 선언

 

Initialization // 폼의 Initialization 블록을 사용하여 로거 

  CodeSiteEx := TCodeSiteLogger.Create(nil); // (finalization 블록에서) 직접 Free 하기로 한다 

  CodeSiteEx.Destination := TCodeSiteDestination.Create(CodeSiteEx); // CodeSiteEx 소멸시, 해당 Destination 오브젝트도 소멸

  CodeSiteEx.Desination.AsString := ‘…..’; // 이때 로그 파일 명은 Errors.csl 로 지정하자.

finalisation

  CodeSiteEx.Free;

 

end.

 

// 2/2 try-excpt 구문 안에서 CodeSiteEx가 작동하도록 하자.

 

try

 

except

  on E: Exception do

  begin

    CodeSiteEx.SendException(FDQuery1.SQL.Text, E); // Error.csl에 따로 또 로그를 남기자.

    CodeSite.SendException(FDQuery1.SQL.Text, E); // 기존에 있던 구문도 유지하여 함께 작동하도록해도 관계 없다.

  end;

 

CodeSite 로거 활성화를 활용한 실전 팁

- (과도한 로그 수집을 피하기 위해 기본 설정인) 일반 로깅은 비활성화 하자.

    - 대신, 오류 또는 익셉션만을 로깅하는 CodeSiteEx를 따로 만들고 평소에는 이것만 작동시키자

- 오류가 발견되고 재현이 어려운 상황이 될 때, 일반 로깅을 활성화하자. 

    - 각 단계가 로깅 (Enter/ExitMethod)될 수 있도록 일반 로거를 설정하자.

    - 이때, 사용자가 직접 로그 수집을 켜고 끌 수 있도록 메뉴로 추가하자.

    - 로그 수집 여부에 따라 화면 배경색을 다르게 하는 등 쉽게 파악되도록 하자.

    - 기타 필요한 정보를 메시지도 일반 로거에 담아서 추가하자

 

(데모) 평소에는 오류 정보만 로깅하다가 꼭 필요할 때에 전체 로깅하기 (45분05초부터)

배포하는 앱의 메뉴에 ‘로그 수집’이라는 메뉴를 만들고 그 아래에 켜기와 끄기 메뉴를 넣는다.

 

// 켜기 메뉴 선택 시 코드

procedure …

begin

  CodeSite.Enabled := True;

  CodeSite.AddSeparator; // 분리선 추가

  CodeSite.Send(‘사용자가 코드사이트 로그를 켬’);

end;

 

// 끄기 메뉴 선택 시 코드

procedure …

begin

  CodeSite.Enabled := False;

end;

 

// 프로젝트 파일에서는 CodeSite.Enabled := False; 로 설정하여 앱 작동 시 일반 로그 수집은 하지 않도록 한다.

 

DelphiCon-CodeSite9-AddUserMenu.png

(그림9. 사용자가 직접 로그 수집을 켜고 끄도록 한다.)

 

CodeSite의 OnSendMsg로 메시지 가로채기와 다루기

- (유료인) 스튜디오 에디션에만 있음

- 오류 횟수 남기기 등 필요한 모든 조치 가능

  TCodeSiteSendMsgEvent = procedure ( Sender: TObject;
 
 MsgData: TCodeSiteMsgData; var Handled: Boolean ) of object;

 

(데모) OnSendMsg로 메시지 가로채기와 다루기 (49분19초부터)

- (이벤트 핸들러를 만들어야 하므로) CodeSiteLogging 유닛은 인터페이스 uses절에 있어야 한다.

- 이벤트 핸들러 프로시저를 만든다.(아래 코드 참조)

- 타이머를 이용하여 스크래치패드에서 모니터리 되도록 한다.(아래 코드 참조)

- FormCreate와 FormDestroy에서 이벤트를 이벤트 핸들러에 연결한다. (아래 코드 참조)

 

procesure TForm42.CodeSiteSendMsgEvent ( Sender: Object;

  MsgData: TCodeSiteMsgData; var Handled: Boolean);

begin

  if MsgData.MsgType = csmException then

    Inc(Exceptions); //Exceptions는 폼 변수이며 Integer 타입

  else

  if MsgData.MsgType = csmError then

    Inc(Errors); //Errors는 폼 변수이며 Integer 타입

 

  Handled := False; //이벤트가 계속 전달되도록 한다

end;

 

procedure TFrom42.Timer1Timer(Sender: Object);

begin

  CodeSiteEx.Send(csmScratchPad, TimeToStr(now) +….

end;

 

procedure TFrom42.FormCreate(Sender: Object);

begin

  CodeSiteEx.OnSendMsg := Self.CodeSiteSendMsgEvent;

end;

 

procedure TFrom42.FormDestroy(Sender: Object);

begin

  CodeSiteEx.OnSendMsg := nil;

end;

 

세션에서 소개한 코드사이트 로깅 테크닉 요약

- CodeSite Dispatcher

- (스튜디오 에디션 전용) 원격 로깅

- 메시지 유형들

- (스튜디오 에디션 전용) ScratchPad

- CodeSite Destination들

- 로거 여러개 사용하기

- 로거 켜기와 끄기

- (스튜디오 에디션 전용) CodeSite OnSendMsg