시간 초과와 진단
SDK의 제한 시간
섹션 제목: “SDK의 제한 시간”클라이언트 옵션의 timeout_ms(1~300000 ms)는 두 가지에 적용됩니다.
- 탐색, 연결, 세션 활성화, 종료의 네트워크 교환 하나하나
pdcomm_opcua_client_begin으로 보낸 요청 하나하나. 이 시간 안에 응답이 와야 합니다.
기본값은 C pdcomm_opcua_client_options_init과 .NET ClientOptions가 10000 ms, Qt·MFC 작업자가 5000 ms입니다. C 예제는 --timeout으로 바꿉니다.
연결을 받은 뒤 아무 응답도 보내지 않는 서버에 1000 ms로 접속하면 1초 뒤 다음 오류가 납니다.
Error: discover failed (SDK status 5): OPC UA timeout요청이 제한 시간을 넘기면 다음 pdcomm_opcua_client_poll이 실패하고 연결이 닫힙니다. 그 뒤의 호출은 PDCOMM_OPCUA_CLOSED를 돌려줍니다. 핸들을 해제하고 다시 연결합니다. Publish 요청은 게시 주기나 keep-alive 주기만큼 늦게 응답하므로, 구독을 쓸 때는 제한 시간을 keep-alive 주기보다 길게 잡습니다.
서버가 응답 하나를 중단(abort chunk)하면 그 요청만 PDCOMM_OPCUA_RUNTIME_ERROR로 끝나고 연결은 유지됩니다. 오류 문장에 서버가 보낸 StatusCode가 들어 있습니다.
시뮬레이터의 제한 시간
섹션 제목: “시뮬레이터의 제한 시간”시뮬레이터 클라이언트의 client.timeout_ms(100~60000 ms, 기본 5000)가 같은 역할을 합니다. 요청이 제한 시간을 넘기면 시뮬레이터는 연결을 닫고 다음 오류를 돌려줍니다.
{"error":"Timeout (client connection closed)","ok":false}Simulator.Delay 메서드로 느린 응답을 재현할 수 있습니다. 제한 시간을 1000 ms로 설정하고 3000 ms를 기다리게 하면 1초 뒤 위 오류가 납니다.
{"action":"configure","config":{"client":{"timeout_ms":1000}}}{"action":"call","method":"ns=2;s=Simulator.Delay","arguments":[{"type":"UInt32","value":3000}]}Simulator.Delay는 시뮬레이터 서버의 처리 스레드를 그 시간 동안 멈춥니다. 그동안 새 연결도 처리되지 않으므로, 바로 connect를 다시 보내면 Timeout이 날 수 있습니다. 대기 시간이 지난 뒤 다시 연결합니다.
요청 취소
섹션 제목: “요청 취소”| 방법 | 동작 |
|---|---|
헤드리스 {"action":"cancel"} |
실행 중인 동작이 Cancelled로 끝납니다. |
| GUI Cancel request | 같은 취소를 요청합니다. |
MCP notifications/cancelled |
해당 요청을 중단하고 응답하지 않습니다. |
취소는 시뮬레이터 클라이언트가 응답을 기다리는 것을 멈출 뿐, 서버에 이미 보낸 요청을 되돌리지 않습니다. 나중에 도착한 응답은 시뮬레이터가 버립니다. state의 client.pending_cancelled가 아직 버리지 못한 응답 수입니다.
오류 정보 읽기
섹션 제목: “오류 정보 읽기”SDK. 실패한 함수 바로 뒤에 같은 스레드에서 pdcomm_opcua_last_error_copy로 오류 문장을 읽습니다. C++의 pdcomm::opcua::error::what(), .NET의 OpcUaException.Message가 같은 문장입니다. 응답의 서비스 결과는 pdcomm_opcua_response_get_info의 service_status, 응답 종류는 binary_id로 확인합니다. binary_id가 397이면 ServiceFault입니다. SDK 라이브러리는 로그 파일을 쓰지 않습니다.
시뮬레이터 동작 기록. {"action":"trace"} 또는 GUI의 Trace & Diagnostics 탭은 최근 동작 1000개를 보여 줍니다. 항목마다 작업 공간, 동작, 성공 여부, 걸린 시간(마이크로초), 대상 노드, 오류 문장이 있습니다.
{"action":"call","elapsed_us":210145,"error":"Cancelled","ok":false,"sequence":3,"time_ms":412,"workspace":"read_write_methods"}서버 감사 기록. {"action":"server_status"}의 audit에 시뮬레이터 서버의 보안 채널, 세션, 사용자 인증 기록이 최근 100개까지 남습니다.
{"action":"user authentication rejected","channel":3,"status":"BadUserAccessDenied (0x801F0000)"}진단 로그
섹션 제목: “진단 로그”시뮬레이터 프로그램(GUI, 헤드리스, MCP)은 진단 로그를 JSON 줄 형식으로 씁니다. 기본으로 꺼져 있습니다.
동작으로 켜기. logging_configure에 설정을 넘깁니다. GUI에서는 Trace & Diagnostics 탭의 **Diagnostic log (off by default)**와 Apply logging을 씁니다.
{"action":"logging_configure","config":{"enabled":true,"level":"debug","file":"logs/opcua-simulator.jsonl"}}| 필드 | 기본값 | 설명 |
|---|---|---|
enabled |
true |
로그를 쓸지 여부 |
level |
info |
error, warn, info, debug, trace |
file |
없음 | 로그 파일. 없으면 표준 오류로 씁니다. 폴더는 미리 있어야 합니다. |
max_bytes |
10485760 | 이 크기를 넘으면 파일을 바꿉니다. |
files |
3 | 보관할 파일 수(1~16) |
forensics |
false |
1초마다 프로세스 상태를 기록합니다. debug 이상에서만 켤 수 있습니다. |
환경 변수로 켜기. 프로그램을 시작할 때부터 기록하려면 환경 변수를 씁니다.
mkdir -p logsPDCOMM_LOG=debug PDCOMM_LOG_FILE=logs/opcua-simulator.jsonl "$OPCUA_APPS/bin/pdcomm-opcua-headless"PDCOMM_LOG(수준), PDCOMM_LOG_FILE, PDCOMM_LOG_MAX_BYTES, PDCOMM_LOG_FILES, PDCOMM_LOG_FORENSICS를 지원합니다.
기록 한 줄은 다음과 같습니다. 실패한 동작은 error 수준으로 남습니다.
{"arch":"aarch64","build_id":"4115d51b3c0114ac8ea1edc0786f07c726b87d8a","component":"service","event":"action_completed","fields":{"action":"connect","elapsed_us":5,"error_code":"ServiceError","success":false},"instance_id":"94497-1791998764824784000","level":"error","monotonic_us":197102,"os":"macos","pid":94497,"protocol":"opcua","request_id":7,"schema_version":1,"sdk_version":"0.1.0","sequence":8,"thread":"ThreadId(1)","timestamp_unix_ms":1791998765021}로그에는 동작 이름, 성공 여부, 오류 분류(Timeout, Cancelled, ServiceError), 걸린 시간이 남습니다. 노드 값, 암호, 개인 키는 남지 않습니다. {"action":"logging_status"}는 쓴 기록 수(written), 버린 기록 수(dropped), 쓰기 오류 수를 보여 주고, {"action":"logging_flush"}는 버퍼를 파일에 씁니다.
| 응답 | 원인과 조치 |
|---|---|
Cannot open logging sink |
로그 파일의 폴더가 없거나 쓸 수 없습니다. 폴더를 만듭니다. |
Invalid logging level |
level 값이 틀렸습니다. |
Forensics requires debug or trace logging |
forensics는 debug나 trace 수준에서만 켭니다. |
문제를 문의할 때는 재현 순서, 오류 문장, 동작 기록, 진단 로그 파일을 함께 보내 주십시오. 로그에는 암호가 남지 않지만, 보내기 전에 파일 경로 같은 내용을 확인합니다.