label-send log 추가

This commit is contained in:
2026-03-11 22:36:50 +09:00
parent 4322e46e3a
commit bfa5e861a2
15 changed files with 156 additions and 16 deletions

View File

@@ -650,7 +650,7 @@ code + .copy-button {
<script type="text/javascript"> <script type="text/javascript">
function configurationCacheProblems() { return ( function configurationCacheProblems() { return (
// begin-report-data // begin-report-data
{"diagnostics":[{"locations":[{}],"problem":[{"text":"Properties should be assigned using the 'propName = value' syntax. Setting a property via the Gradle-generated 'propName value' or 'propName(value)' syntax in Groovy DSL has been deprecated."}],"severity":"WARNING","problemDetails":[{"text":"This is scheduled to be removed in Gradle 10.0."}],"contextualLabel":"Properties should be assigned using the 'propName = value' syntax. Setting a property via the Gradle-generated 'propName value' or 'propName(value)' syntax in Groovy DSL has been deprecated.","documentationLink":"https://docs.gradle.org/8.14/userguide/upgrading_version_8.html#groovy_space_assignment_syntax","problemId":[{"name":"deprecation","displayName":"Deprecation"},{"name":"properties-should-be-assigned-using-the-propname-value-syntax-setting-a-property-via-the-gradle-generated-propname-value-or-propname-value-syntax-in-groovy-dsl","displayName":"Properties should be assigned using the 'propName = value' syntax. Setting a property via the Gradle-generated 'propName value' or 'propName(value)' syntax in Groovy DSL has been deprecated."}],"solutions":[[{"text":"Use assignment ('url = <value>') instead."}]]}],"problemsReport":{"totalProblemCount":1,"buildName":"kamco-label-send-job","requestedTasks":":classes","documentationLink":"https://docs.gradle.org/8.14/userguide/reporting_problems.html","documentationLinkCaption":"Problem report","summaries":[]}} {"diagnostics":[{"locations":[{}],"problem":[{"text":"Properties should be assigned using the 'propName = value' syntax. Setting a property via the Gradle-generated 'propName value' or 'propName(value)' syntax in Groovy DSL has been deprecated."}],"severity":"WARNING","problemDetails":[{"text":"This is scheduled to be removed in Gradle 10.0."}],"contextualLabel":"Properties should be assigned using the 'propName = value' syntax. Setting a property via the Gradle-generated 'propName value' or 'propName(value)' syntax in Groovy DSL has been deprecated.","documentationLink":"https://docs.gradle.org/8.14/userguide/upgrading_version_8.html#groovy_space_assignment_syntax","problemId":[{"name":"deprecation","displayName":"Deprecation"},{"name":"properties-should-be-assigned-using-the-propname-value-syntax-setting-a-property-via-the-gradle-generated-propname-value-or-propname-value-syntax-in-groovy-dsl","displayName":"Properties should be assigned using the 'propName = value' syntax. Setting a property via the Gradle-generated 'propName value' or 'propName(value)' syntax in Groovy DSL has been deprecated."}],"solutions":[[{"text":"Use assignment ('url = <value>') instead."}]]},{"locations":[{"path":"C:\\workspace\\kamco-cd-cron\\gukyuin\\label-send\\src\\main\\java\\com\\kamco\\cd\\kamcoback\\config\\resttemplate\\ExternalHttpClient.java"},{"taskPath":":compileJava"}],"problem":[{"text":"Some input files use or override a deprecated API."}],"severity":"ADVICE","problemDetails":[{"text":"Note: Some input files use or override a deprecated API."}],"contextualLabel":"Some input files use or override a deprecated API.","problemId":[{"name":"java","displayName":"Java compilation"},{"name":"compilation","displayName":"Compilation"},{"name":"compiler.note.deprecated.plural","displayName":"Some input files use or override a deprecated API."}]},{"locations":[{"path":"C:\\workspace\\kamco-cd-cron\\gukyuin\\label-send\\src\\main\\java\\com\\kamco\\cd\\kamcoback\\config\\resttemplate\\ExternalHttpClient.java"},{"taskPath":":compileJava"}],"problem":[{"text":"Recompile with -Xlint:deprecation for details."}],"severity":"ADVICE","problemDetails":[{"text":"Note: Recompile with -Xlint:deprecation for details."}],"contextualLabel":"Recompile with -Xlint:deprecation for details.","problemId":[{"name":"java","displayName":"Java compilation"},{"name":"compilation","displayName":"Compilation"},{"name":"compiler.note.deprecated.recompile","displayName":"Recompile with -Xlint:deprecation for details."}]},{"locations":[{"path":"C:\\workspace\\kamco-cd-cron\\gukyuin\\label-send\\src\\main\\java\\com\\kamco\\cd\\kamcoback\\common\\utils\\enums\\Enums.java"},{"taskPath":":compileJava"}],"problem":[{"text":"Some input files use unchecked or unsafe operations."}],"severity":"ADVICE","problemDetails":[{"text":"Note: Some input files use unchecked or unsafe operations."}],"contextualLabel":"Some input files use unchecked or unsafe operations.","problemId":[{"name":"java","displayName":"Java compilation"},{"name":"compilation","displayName":"Compilation"},{"name":"compiler.note.unchecked.plural","displayName":"Some input files use unchecked or unsafe operations."}]},{"locations":[{"path":"C:\\workspace\\kamco-cd-cron\\gukyuin\\label-send\\src\\main\\java\\com\\kamco\\cd\\kamcoback\\common\\utils\\enums\\Enums.java"},{"taskPath":":compileJava"}],"problem":[{"text":"Recompile with -Xlint:unchecked for details."}],"severity":"ADVICE","problemDetails":[{"text":"Note: Recompile with -Xlint:unchecked for details."}],"contextualLabel":"Recompile with -Xlint:unchecked for details.","problemId":[{"name":"java","displayName":"Java compilation"},{"name":"compilation","displayName":"Compilation"},{"name":"compiler.note.unchecked.recompile","displayName":"Recompile with -Xlint:unchecked for details."}]}],"problemsReport":{"totalProblemCount":5,"buildName":"kamco-label-send-job","requestedTasks":"clean build","documentationLink":"https://docs.gradle.org/8.14/userguide/reporting_problems.html","documentationLinkCaption":"Problem report","summaries":[]}}
// end-report-data // end-report-data
);} );}
</script> </script>

View File

@@ -25,46 +25,105 @@ public class ExternalHttpClient {
public <T> ExternalCallResult<T> call( public <T> ExternalCallResult<T> call(
String url, HttpMethod method, Object body, HttpHeaders headers, Class<T> responseType) { String url, HttpMethod method, Object body, HttpHeaders headers, Class<T> responseType) {
long start = System.currentTimeMillis();
log.info("[API-REQ] method={}, url={}", method, url);
// responseType 기반으로 Accept 동적 세팅 // responseType 기반으로 Accept 동적 세팅
HttpHeaders resolvedHeaders = resolveHeaders(headers, responseType); HttpHeaders resolvedHeaders = resolveHeaders(headers, responseType);
log.debug("[API-REQ] headers={}", resolvedHeaders);
logRequestBody(body); logRequestBody(body);
HttpEntity<Object> entity = new HttpEntity<>(body, resolvedHeaders); HttpEntity<Object> entity = new HttpEntity<>(body, resolvedHeaders);
try { try {
// String: raw bytes -> UTF-8 string // String: raw bytes -> UTF-8 string
if (responseType == String.class) { if (responseType == String.class) {
ResponseEntity<byte[]> res = restTemplate.exchange(url, method, entity, byte[].class); ResponseEntity<byte[]> res = restTemplate.exchange(url, method, entity, byte[].class);
String raw = String raw =
(res.getBody() == null) ? null : new String(res.getBody(), StandardCharsets.UTF_8); (res.getBody() == null) ? null : new String(res.getBody(), StandardCharsets.UTF_8);
long elapsed = System.currentTimeMillis() - start;
log.info(
"[API-RES] method={}, url={}, status={}, elapsed={}ms",
method,
url,
res.getStatusCodeValue(),
elapsed);
log.debug("[API-RES] body={}", raw);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
T casted = (T) raw; T casted = (T) raw;
return new ExternalCallResult<>(res.getStatusCodeValue(), true, casted, null); return new ExternalCallResult<>(res.getStatusCodeValue(), true, casted, null);
} }
// byte[]: raw bytes로 받고, JSON이면 에러로 처리 // byte[]: raw bytes로 받고, JSON이면 에러로 처리
if (responseType == byte[].class) { if (responseType == byte[].class) {
ResponseEntity<byte[]> res = restTemplate.exchange(url, method, entity, byte[].class); ResponseEntity<byte[]> res = restTemplate.exchange(url, method, entity, byte[].class);
long elapsed = System.currentTimeMillis() - start;
log.info(
"[API-RES] method={}, url={}, status={}, elapsed={}ms",
method,
url,
res.getStatusCodeValue(),
elapsed);
MediaType ct = res.getHeaders().getContentType(); MediaType ct = res.getHeaders().getContentType();
byte[] bytes = res.getBody(); byte[] bytes = res.getBody();
if (isJsonLike(ct)) { if (isJsonLike(ct)) {
String err = (bytes == null) ? null : new String(bytes, StandardCharsets.UTF_8); String err = (bytes == null) ? null : new String(bytes, StandardCharsets.UTF_8);
log.warn("[API-RES] JSON error body={}", err);
return new ExternalCallResult<>(res.getStatusCodeValue(), false, null, err); return new ExternalCallResult<>(res.getStatusCodeValue(), false, null, err);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
T casted = (T) bytes; T casted = (T) bytes;
return new ExternalCallResult<>(res.getStatusCodeValue(), true, casted, null); return new ExternalCallResult<>(res.getStatusCodeValue(), true, casted, null);
} }
// DTO 등: 일반 역직렬화 // DTO 등: 일반 역직렬화
ResponseEntity<T> res = restTemplate.exchange(url, method, entity, responseType); ResponseEntity<T> res = restTemplate.exchange(url, method, entity, responseType);
long elapsed = System.currentTimeMillis() - start;
log.info(
"[API-RES] method={}, url={}, status={}, elapsed={}ms",
method,
url,
res.getStatusCodeValue(),
elapsed);
log.debug("[API-RES] body={}", res.getBody());
return new ExternalCallResult<>(res.getStatusCodeValue(), true, res.getBody(), null); return new ExternalCallResult<>(res.getStatusCodeValue(), true, res.getBody(), null);
} catch (HttpStatusCodeException e) { } catch (HttpStatusCodeException e) {
long elapsed = System.currentTimeMillis() - start;
log.error(
"[API-ERROR] method={}, url={}, status={}, elapsed={}ms, body={}",
method,
url,
e.getStatusCode().value(),
elapsed,
e.getResponseBodyAsString());
return new ExternalCallResult<>( return new ExternalCallResult<>(
e.getStatusCode().value(), false, null, e.getResponseBodyAsString()); e.getStatusCode().value(), false, null, e.getResponseBodyAsString());
} }

View File

@@ -28,29 +28,110 @@ public class GukYuinApiLabelJobService {
/** 어제 라벨링 검수 완료된 것 -> 국유인에 전송 */ /** 어제 라벨링 검수 완료된 것 -> 국유인에 전송 */
public void findLabelingCompleteSend(LocalDate baseDate) { public void findLabelingCompleteSend(LocalDate baseDate) {
log.info("[Step 1-1] 어제 검수완료된 라벨링을 검색한다."); long jobStart = System.currentTimeMillis();
log.info("=== baseDate : {}", baseDate);
log.info("=== baseDate 있으면 해당 일자, 없으면 어제일자로 조회"); log.info("[JOB-START] Labeling Send Job start profile={}, baseDate={}", profile, baseDate);
log.info("[Step 1-1] 어제 검수완료된 라벨링 조회 시작");
log.info("baseDate: {}", baseDate);
log.info("baseDate가 없으면 오늘 00시 이전까지 검수완료된 건들을 조회한다.");
log.info("baseDate가 있으면 baseDate 까지 검수완료된 건들을 조회한다.");
List<GeomUidDto> list = gukYuinLabelJobCoreService.findYesterdayLabelingCompleteList(baseDate); List<GeomUidDto> list = gukYuinLabelJobCoreService.findYesterdayLabelingCompleteList(baseDate);
log.info("[Step 1-2] 검수완료된 폴리곤 객체 수 : {}", list == null ? 0 : list.size());
if (list.isEmpty()) { int total = list == null ? 0 : list.size();
log.info("[Step 1-3] 객체 없어서 return : 스케줄링 종료");
log.info("[Step 1-2] 검수완료된 폴리곤 객체 수={}", total);
if (list == null || list.isEmpty()) {
log.info("[Step 1-3] 처리 대상 없음 → 스케줄 종료");
log.info("[JOB-END] total=0 elapsed={}ms", System.currentTimeMillis() - jobStart);
return; return;
} }
int success = 0;
int fail = 0;
int skip = 0;
log.info("[Step 2-1] 객체 목록으로 라벨링 전송 API 호출 시작"); log.info("[Step 2-1] 객체 목록으로 라벨링 전송 API 호출 시작");
int index = 0;
for (GeomUidDto gto : list) { for (GeomUidDto gto : list) {
log.info("[Step 2-2] 객체ID 확인 gto.getResultUid(): {}", gto.getResultUid());
ChngDetectContDto.ResultLabelDto dto = index++;
gukYuinApiService.updateChnDtctObjtLabelingYn(gto.getResultUid(), "Y", "Y"); long itemStart = System.currentTimeMillis();
log.info("[Step 2-3] 결과 dto.getSuccess(): {}", dto.getSuccess());
if (dto.getSuccess()) { try {
log.info("[Step 2-4] 결과가 성공일 때 inference_geom에 label_send_dttm 업데이트 하기");
log.info("==== 업데이트 하는 객체 gto.getGeoUid(): {}", gto.getGeoUid()); log.info(
// inference_geom 에 label_send_dttm 업데이트 하기 "[Step 2-2] 처리 시작 {}/{} resultUid={}, geoUid={}",
gukYuinLabelJobCoreService.updateAnalDataInferenceGeomSendDttm(gto.getGeoUid()); index,
total,
gto.getResultUid(),
gto.getGeoUid());
long apiStart = System.currentTimeMillis();
ChngDetectContDto.ResultLabelDto dto =
gukYuinApiService.updateChnDtctObjtLabelingYn(gto.getResultUid(), "Y", "Y");
long apiElapsed = System.currentTimeMillis() - apiStart;
if (dto == null) {
log.warn("[Step 2-3] API 결과 NULL resultUid={}", gto.getResultUid());
skip++;
continue;
}
log.info(
"[Step 2-3] API 결과 success={}, elapsed={}ms resultUid={}",
dto.getSuccess(),
apiElapsed,
gto.getResultUid());
log.debug("[Step 2-3] API result DTO={}", dto);
if (dto.getSuccess()) {
log.info(
"[Step 2-4] 성공 → inference_geom label_send_dttm 업데이트 geoUid={}", gto.getGeoUid());
gukYuinLabelJobCoreService.updateAnalDataInferenceGeomSendDttm(gto.getGeoUid());
success++;
} else {
log.warn("[Step 2-4] API 성공 false → DB 업데이트 skip resultUid={}", gto.getResultUid());
skip++;
}
log.info(
"[ITEM-END] resultUid={} elapsed={}ms",
gto.getResultUid(),
System.currentTimeMillis() - itemStart);
} catch (Exception e) {
fail++;
log.error(
"[ITEM-ERROR] resultUid={} geoUid={} elapsed={}ms",
gto.getResultUid(),
gto.getGeoUid(),
System.currentTimeMillis() - itemStart,
e);
} }
} }
log.info(
"[JOB-END] total={}, success={}, skip={}, fail={}, elapsed={}ms",
total,
success,
skip,
fail,
System.currentTimeMillis() - jobStart);
} }
} }