Skip to content

Commit eb5cecc

Browse files
committed
fix: add missing FinalMetricDataList to LocalTrainingJob
1 parent 46ac17f commit eb5cecc

File tree

1 file changed

+43
-8
lines changed

1 file changed

+43
-8
lines changed

src/sagemaker/local/entities.py

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,25 @@
1313
"""Placeholder docstring"""
1414
from __future__ import absolute_import
1515

16-
import enum
1716
import datetime
17+
import enum
1818
import json
1919
import logging
2020
import os
21+
import re
2122
import tempfile
2223
import time
23-
from uuid import uuid4
2424
from copy import deepcopy
25+
from uuid import uuid4
26+
2527
from botocore.exceptions import ClientError
2628

2729
import sagemaker.local.data
28-
29-
from sagemaker.local.image import _SageMakerContainer
30-
from sagemaker.local.utils import copy_directory_structure, move_to_destination, get_docker_host
31-
from sagemaker.utils import DeferredError, get_config_value, format_tags
3230
from sagemaker.local.exceptions import StepExecutionException
31+
from sagemaker.local.image import _SageMakerContainer
32+
from sagemaker.local.utils import (copy_directory_structure, get_docker_host,
33+
move_to_destination)
34+
from sagemaker.utils import DeferredError, format_tags, get_config_value
3335

3436
logger = logging.getLogger(__name__)
3537

@@ -272,9 +274,42 @@ def describe(self):
272274
"AlgorithmSpecification": {
273275
"ContainerEntrypoint": self.container.container_entrypoint,
274276
},
277+
"FinalMetricDataList": self._extract_final_metrics()
275278
}
276279
return response
277280

281+
def _extract_final_metrics(self):
282+
"""Extract metrics from container logs using metric definitions."""
283+
if not hasattr(self.container, 'logs') or not self.container.logs:
284+
return []
285+
286+
# Get metric definitions from container
287+
metric_definitions = getattr(self.container, 'metric_definitions', [])
288+
if not metric_definitions:
289+
return []
290+
291+
final_metrics = []
292+
logs = self.container.logs
293+
294+
for metric_def in metric_definitions:
295+
metric_name = metric_def.get('Name')
296+
regex_pattern = metric_def.get('Regex')
297+
298+
if not metric_name or not regex_pattern:
299+
continue
300+
301+
# Find all matches in logs
302+
matches = re.findall(regex_pattern, logs)
303+
if matches:
304+
# Use the last match as final metric
305+
final_value = float(matches[-1])
306+
final_metrics.append({
307+
'MetricName': metric_name,
308+
'Value': final_value,
309+
'Timestamp': self.end_time or datetime.now()
310+
})
311+
312+
return final_metrics
278313

279314
class _LocalTransformJob(object):
280315
"""Placeholder docstring"""
@@ -711,8 +746,8 @@ def __init__(
711746
PipelineExecutionDisplayName=None,
712747
local_session=None,
713748
):
714-
from sagemaker.workflow.pipeline import PipelineGraph
715749
from sagemaker import LocalSession
750+
from sagemaker.workflow.pipeline import PipelineGraph
716751

717752
self.pipeline = pipeline
718753
self.pipeline_execution_name = execution_id
@@ -809,7 +844,7 @@ def mark_step_executing(self, step_name):
809844

810845
def _initialize_step_execution(self, steps):
811846
"""Initialize step_execution dict."""
812-
from sagemaker.workflow.steps import StepTypeEnum, Step
847+
from sagemaker.workflow.steps import Step, StepTypeEnum
813848

814849
supported_steps_types = (
815850
StepTypeEnum.TRAINING,

0 commit comments

Comments
 (0)