Skip to content

Commit 059f2b4

Browse files
authored
Enhance purview registry error messages (#709)
* Enhance purview registry error messages * Update doc for REGISTRY_DEBUGGING
1 parent 5e7edf6 commit 059f2b4

File tree

3 files changed

+70
-17
lines changed

3 files changed

+70
-17
lines changed

docs/dev_guide/build-and-push-feathr-registry-docker-image.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,8 @@ docker push feathrfeaturestore/feathr-registry
7676

7777
## Published Feathr Registry Image
7878

79-
The published feathr feature registry is located in [DockerHub here](https://hub.docker.com/r/feathrfeaturestore/feathr-registry).
79+
The published feathr feature registry is located in [DockerHub here](https://hub.docker.com/r/feathrfeaturestore/feathr-registry).
80+
81+
## Include the detailed track back info in registry api HTTP error response
82+
83+
Set environment REGISTRY_DEBUGGING to any non empty string will enable the detailed track back info in registry api http response. This variable is helpful for python client debugging and should only be used for debugging purposes.

registry/purview-registry/main.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import os
2+
import traceback
23
from re import sub
34
from typing import Optional
45
from uuid import UUID
56
from fastapi import APIRouter, FastAPI, HTTPException
7+
from fastapi.responses import JSONResponse
68
from starlette.middleware.cors import CORSMiddleware
7-
from registry import *
8-
from registry.purview_registry import PurviewRegistry
9+
from registry.purview_registry import PurviewRegistry, ConflictError
910
from registry.models import AnchorDef, AnchorFeatureDef, DerivedFeatureDef, EntityType, ProjectDef, SourceDef, to_snake
1011

1112
rp = "/v1"
@@ -43,6 +44,48 @@ def to_camel(s):
4344
allow_headers=["*"],
4445
)
4546

47+
def exc_to_content(e: Exception) -> dict:
48+
content={"message": str(e)}
49+
if os.environ.get("REGISTRY_DEBUGGING"):
50+
content["traceback"] = "".join(traceback.TracebackException.from_exception(e).format())
51+
return content
52+
53+
@app.exception_handler(ConflictError)
54+
async def conflict_error_handler(_, exc: ConflictError):
55+
return JSONResponse(
56+
status_code=409,
57+
content=exc_to_content(exc),
58+
)
59+
60+
61+
@app.exception_handler(ValueError)
62+
async def value_error_handler(_, exc: ValueError):
63+
return JSONResponse(
64+
status_code=400,
65+
content=exc_to_content(exc),
66+
)
67+
68+
@app.exception_handler(TypeError)
69+
async def type_error_handler(_, exc: ValueError):
70+
return JSONResponse(
71+
status_code=400,
72+
content=exc_to_content(exc),
73+
)
74+
75+
76+
@app.exception_handler(KeyError)
77+
async def key_error_handler(_, exc: KeyError):
78+
return JSONResponse(
79+
status_code=404,
80+
content=exc_to_content(exc),
81+
)
82+
83+
@app.exception_handler(IndexError)
84+
async def index_error_handler(_, exc: IndexError):
85+
return JSONResponse(
86+
status_code=404,
87+
content=exc_to_content(exc),
88+
)
4689

4790
@router.get("/projects",tags=["Project"])
4891
def get_projects() -> list[str]:

registry/purview-registry/registry/purview_registry.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import copy
2-
from http.client import CONFLICT, HTTPException
32
import itertools
4-
from typing import Any, Optional, Tuple, Union
5-
from urllib.error import HTTPError
3+
from typing import Optional, Tuple, Union
64
from uuid import UUID
75

86
from azure.identity import DefaultAzureCredential
@@ -11,7 +9,7 @@
119
from pyapacheatlas.core import (AtlasEntity, AtlasProcess,
1210
PurviewClient)
1311
from pyapacheatlas.core.typedef import (AtlasAttributeDef,Cardinality,EntityTypeDef)
14-
from pyapacheatlas.core.util import GuidTracker
12+
from pyapacheatlas.core.util import GuidTracker, AtlasException
1513
from pyhocon import ConfigFactory
1614

1715
from registry.interface import Registry
@@ -23,6 +21,10 @@
2321
TYPEDEF_ARRAY_ANCHOR=f"array<feathr_anchor_v1>"
2422
TYPEDEF_ARRAY_DERIVED_FEATURE=f"array<feathr_derived_feature_v1>"
2523
TYPEDEF_ARRAY_ANCHOR_FEATURE=f"array<feathr_anchor_feature_v1>"
24+
25+
class ConflictError(Exception):
26+
pass
27+
2628
class PurviewRegistry(Registry):
2729
def __init__(self,azure_purview_name: str, registry_delimiter: str = "__", credential=None,register_types = True):
2830
self.registry_delimiter = registry_delimiter
@@ -568,18 +570,22 @@ def _register_feathr_feature_types(self):
568570
def _upload_entity_batch(self, entity_batch:list[AtlasEntity]):
569571
# we only support entity creation, update is not supported.
570572
# setting lastModifiedTS ==0 will ensure this, if another entity with ts>=1 exist
571-
# upload funtion will fail with 412 Precondition fail.
573+
# upload function will fail with 412 Precondition fail.
572574
for entity in entity_batch:
573575
entity.lastModifiedTS="0"
574-
results = self.purview_client.upload_entities(
575-
batch=entity)
576-
if results:
577-
dict = {x.guid: x for x in entity_batch}
578-
for k, v in results['guidAssignments'].items():
579-
dict[k].guid = v
580-
else:
581-
raise RuntimeError("Feature registration failed.", results)
582-
576+
try:
577+
results = self.purview_client.upload_entities(
578+
batch=entity)
579+
if results:
580+
dict = {x.guid: x for x in entity_batch}
581+
for k, v in results['guidAssignments'].items():
582+
dict[k].guid = v
583+
else:
584+
raise RuntimeError("Feature registration failed.", results)
585+
except AtlasException as e:
586+
if "PreConditionCheckFailed" in e.args[0]:
587+
raise ConflictError(f"Entity {entity.guid}, {entity.typeName} -- {entity.qualifiedName} already exists in Purview. Please use a new name.")
588+
583589
def _generate_fully_qualified_name(self, segments):
584590
return self.registry_delimiter.join(segments)
585591

0 commit comments

Comments
 (0)