Skip to content

Commit 24f8925

Browse files
author
Yi-Ting Lee
committed
merge integ load test
2 parents 09264c2 + 83964da commit 24f8925

File tree

5 files changed

+199
-3
lines changed

5 files changed

+199
-3
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
urllib3==1.26.8
22
docker-compose==1.29.2
33
docker~=5.0.0
4-
PyYAML==5.4.1
4+
PyYAML==5.4.1

requirements/extras/test_requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ fabric==2.6.0
1818
requests==2.27.1
1919
sagemaker-experiments==0.1.35
2020
Jinja2==3.0.3
21+
pyvis==0.2.1

src/sagemaker/lineage/query.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ def _get_visualization_elements(self):
364364
elements = {"nodes": verts, "edges": edges}
365365
return elements
366366

367-
def visualize(self):
367+
def visualize(self, path="pyvisExample.html"):
368368
"""Visualize lineage query result."""
369369
lineage_graph = {
370370
# nodes can have shape / color
@@ -398,7 +398,7 @@ def visualize(self):
398398

399399
pyvis_vis = PyvisVisualizer(lineage_graph)
400400
elements = self._get_visualization_elements()
401-
return pyvis_vis.render(elements=elements)
401+
return pyvis_vis.render(elements=elements, path=path)
402402

403403

404404
class LineageFilter(object):

tests/integ/sagemaker/lineage/helpers.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@
1212
# language governing permissions and limitations under the License.
1313
"""This module contains helper methods for tests of SageMaker Lineage"""
1414
from __future__ import absolute_import
15+
from urllib import response
1516

1617
import uuid
1718
from datetime import datetime
1819
import time
20+
import boto3
21+
from botocore.config import Config
22+
from sagemaker.lineage import association
23+
from sagemaker.lineage.artifact import Artifact
24+
from sagemaker.lineage.association import Association
1925

2026

2127
def name():
@@ -78,3 +84,96 @@ def visit(arn, visited: set):
7884

7985
ret = []
8086
return visit(start_arn, set())
87+
88+
89+
class LineageResourceHelper:
90+
def __init__(self, sagemaker_session):
91+
self.client = sagemaker_session.sagemaker_client
92+
self.artifacts = []
93+
self.actions = []
94+
self.contexts = []
95+
self.trialComponents = []
96+
self.associations = []
97+
98+
def create_artifact(self, artifact_name, artifact_type="Dataset"):
99+
response = self.client.create_artifact(
100+
ArtifactName=artifact_name,
101+
Source={
102+
"SourceUri": "Test-artifact-" + artifact_name,
103+
"SourceTypes": [
104+
{"SourceIdType": "S3ETag", "Value": "Test-artifact-sourceId-value"},
105+
],
106+
},
107+
ArtifactType=artifact_type,
108+
)
109+
self.artifacts.append(response["ArtifactArn"])
110+
111+
return response["ArtifactArn"]
112+
113+
def create_action(self, action_name, action_type="ModelDeployment"):
114+
response = self.client.create_action(
115+
ActionName=action_name,
116+
Source={
117+
"SourceUri": "Test-action-" + action_name,
118+
"SourceTypes": [
119+
{"SourceIdType": "S3ETag", "Value": "Test-action-sourceId-value"},
120+
],
121+
},
122+
ActionType=action_type
123+
)
124+
self.actions.append(response["ActionArn"])
125+
126+
return response["ActionArn"]
127+
128+
def create_context(self, context_name, context_type="Endpoint"):
129+
response = self.client.create_context(
130+
ContextName=context_name,
131+
Source={
132+
"SourceUri": "Test-context-" + context_name,
133+
"SourceTypes": [
134+
{"SourceIdType": "S3ETag", "Value": "Test-context-sourceId-value"},
135+
],
136+
},
137+
ContextType=context_type
138+
)
139+
self.contexts.append(response["ContextArn"])
140+
141+
return response["ContextArn"]
142+
143+
def create_trialComponent(self, trialComponent_name, trialComponent_type="TrainingJob"):
144+
response = self.client.create_trial_component(
145+
TrialComponentName=trialComponent_name,
146+
147+
)
148+
149+
def create_association(self, source_arn, dest_arn, association_type="AssociatedWith"):
150+
response = self.client.add_association(
151+
SourceArn=source_arn, DestinationArn=dest_arn, AssociationType=association_type
152+
)
153+
if "SourceArn" in response.keys():
154+
self.associations.append((source_arn, dest_arn))
155+
return True
156+
else:
157+
return False
158+
159+
def clean_all(self):
160+
for source, dest in self.associations:
161+
try:
162+
self.client.delete_association(SourceArn=source, DestinationArn=dest)
163+
time.sleep(0.5)
164+
except Exception as e:
165+
print("skipped " + str(e))
166+
167+
for artifact_arn in self.artifacts:
168+
try:
169+
self.client.delete_artifact(ArtifactArn=artifact_arn)
170+
time.sleep(0.5)
171+
except Exception as e:
172+
print("skipped " + str(e))
173+
174+
for action_arn in self.actions:
175+
try:
176+
self.client.delete_action(ActionArn=action_arn)
177+
time.sleep(0.5)
178+
except Exception as e:
179+
print("skipped " + str(e))
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
"""This module contains code to test SageMaker ``LineageQueryResult.visualize()``"""
14+
15+
import datetime
16+
import logging
17+
import time
18+
19+
import pytest
20+
21+
import sagemaker.lineage.query
22+
from sagemaker.lineage.query import LineageQueryDirectionEnum
23+
from tests.integ.sagemaker.lineage.helpers import name, names, retry, LineageResourceHelper
24+
25+
26+
def test_LineageResourceHelper(sagemaker_session):
27+
# check if LineageResourceHelper works properly
28+
lineage_resource_helper = LineageResourceHelper(sagemaker_session=sagemaker_session)
29+
try:
30+
art1 = lineage_resource_helper.create_artifact(artifact_name=name())
31+
art2 = lineage_resource_helper.create_artifact(artifact_name=name())
32+
lineage_resource_helper.create_association(source_arn=art1, dest_arn=art2)
33+
lineage_resource_helper.clean_all()
34+
except Exception as e:
35+
print(e)
36+
assert False
37+
38+
@pytest.mark.skip("visualizer load test")
39+
def test_wide_graph_visualize(sagemaker_session):
40+
lineage_resource_helper = LineageResourceHelper(sagemaker_session=sagemaker_session)
41+
wide_graph_root_arn = lineage_resource_helper.create_artifact(artifact_name=name())
42+
43+
# create wide graph
44+
# Artifact ----> Artifact
45+
# \ \ \-> Artifact
46+
# \ \--> Artifact
47+
# \---> ...
48+
try:
49+
for i in range(500):
50+
artifact_arn = lineage_resource_helper.create_artifact(artifact_name=name())
51+
lineage_resource_helper.create_association(source_arn=wide_graph_root_arn, dest_arn=artifact_arn)
52+
except Exception as e:
53+
print(e)
54+
lineage_resource_helper.clean_all()
55+
assert False
56+
57+
try:
58+
lq = sagemaker.lineage.query.LineageQuery(sagemaker_session)
59+
lq_result = lq.query(start_arns=[wide_graph_root_arn])
60+
lq_result.visualize(path="wideGraph.html")
61+
except Exception as e:
62+
print(e)
63+
lineage_resource_helper.clean_all()
64+
assert False
65+
66+
lineage_resource_helper.clean_all()
67+
68+
@pytest.mark.skip("visualizer load test")
69+
def test_long_graph_visualize(sagemaker_session):
70+
lineage_resource_helper = LineageResourceHelper(sagemaker_session=sagemaker_session)
71+
long_graph_root_arn = lineage_resource_helper.create_artifact(artifact_name=name())
72+
last_arn = long_graph_root_arn
73+
74+
# create long graph
75+
# Artifact -> Artifact -> ... -> Artifact
76+
try:
77+
for i in range(20):
78+
new_artifact_arn = lineage_resource_helper.create_artifact(artifact_name=name())
79+
lineage_resource_helper.create_association(source_arn=last_arn, dest_arn=new_artifact_arn)
80+
last_arn = new_artifact_arn
81+
except Exception as e:
82+
print(e)
83+
lineage_resource_helper.clean_all()
84+
assert False
85+
86+
try:
87+
lq = sagemaker.lineage.query.LineageQuery(sagemaker_session)
88+
lq_result = lq.query(start_arns=[long_graph_root_arn], direction=LineageQueryDirectionEnum.DESCENDANTS)
89+
# max depth = 10 -> graph rendered only has length of ten (in DESCENDANTS direction)
90+
lq_result.visualize(path="longGraph.html")
91+
except Exception as e:
92+
print(e)
93+
lineage_resource_helper.clean_all()
94+
assert False
95+
96+
lineage_resource_helper.clean_all()

0 commit comments

Comments
 (0)