diff --git a/core/src/main/java/feast/core/grpc/CoreServiceImpl.java b/core/src/main/java/feast/core/grpc/CoreServiceImpl.java index 661bbe24039..120323a596b 100644 --- a/core/src/main/java/feast/core/grpc/CoreServiceImpl.java +++ b/core/src/main/java/feast/core/grpc/CoreServiceImpl.java @@ -156,7 +156,7 @@ public void createProject( responseObserver.onNext(CreateProjectResponse.getDefaultInstance()); responseObserver.onCompleted(); } catch (Exception e) { - log.error("Exception has occurred in the createProject method: ", e); + log.error("Exception has occurred in the CreateProject method: ", e); responseObserver.onError( Status.INTERNAL.withDescription(e.getMessage()).withCause(e).asRuntimeException()); } @@ -170,7 +170,7 @@ public void archiveProject( responseObserver.onNext(ArchiveProjectResponse.getDefaultInstance()); responseObserver.onCompleted(); } catch (Exception e) { - log.error("Exception has occurred in the createProject method: ", e); + log.error("Exception has occurred in the ArchiveProject method: ", e); responseObserver.onError( Status.INTERNAL.withDescription(e.getMessage()).withCause(e).asRuntimeException()); } @@ -187,7 +187,7 @@ public void listProjects( .build()); responseObserver.onCompleted(); } catch (Exception e) { - log.error("Exception has occurred in the listProjects method: ", e); + log.error("Exception has occurred in the ListProjects method: ", e); responseObserver.onError( Status.INTERNAL.withDescription(e.getMessage()).withCause(e).asRuntimeException()); } diff --git a/core/src/main/java/feast/core/model/FeatureSet.java b/core/src/main/java/feast/core/model/FeatureSet.java index 232a5f67d14..d1348458371 100644 --- a/core/src/main/java/feast/core/model/FeatureSet.java +++ b/core/src/main/java/feast/core/model/FeatureSet.java @@ -352,6 +352,10 @@ private void setFeatureSpecFields(FeatureSpec.Builder featureSpecBuilder, Field featureSpecBuilder.setTimeOfDayDomain( TimeOfDayDomain.parseFrom(featureField.getTimeOfDayDomain())); } + + if (featureField.getLabels() != null) { + featureSpecBuilder.putAllLabels(featureField.getLabelsJSON()); + } } /** diff --git a/core/src/main/java/feast/core/model/Field.java b/core/src/main/java/feast/core/model/Field.java index cb23e4eceb7..ef67d942756 100644 --- a/core/src/main/java/feast/core/model/Field.java +++ b/core/src/main/java/feast/core/model/Field.java @@ -18,8 +18,10 @@ import feast.core.FeatureSetProto.EntitySpec; import feast.core.FeatureSetProto.FeatureSpec; +import feast.core.util.TypeConversion; import feast.types.ValueProto.ValueType; import java.util.Arrays; +import java.util.Map; import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; @@ -47,6 +49,10 @@ public class Field { @Column(name = "project") private String project; + // Labels that this field belongs to + @Column(name = "labels", columnDefinition = "text") + private String labels; + // Presence constraints (refer to proto feast.core.FeatureSet.FeatureSpec) // Only one of them can be set. private byte[] presence; @@ -82,6 +88,7 @@ public Field(String name, ValueType.Enum type) { public Field(FeatureSpec featureSpec) { this.name = featureSpec.getName(); this.type = featureSpec.getValueType().toString(); + this.labels = TypeConversion.convertMapToJsonString(featureSpec.getLabelsMap()); switch (featureSpec.getPresenceConstraintsCase()) { case PRESENCE: @@ -215,6 +222,10 @@ public Field(EntitySpec entitySpec) { } } + public Map getLabelsJSON() { + return TypeConversion.convertJsonStringToMap(this.labels); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/protos/feast/core/FeatureSet.proto b/protos/feast/core/FeatureSet.proto index 429d99c8547..d58e501c7b6 100644 --- a/protos/feast/core/FeatureSet.proto +++ b/protos/feast/core/FeatureSet.proto @@ -156,6 +156,9 @@ message FeatureSpec { tensorflow.metadata.v0.TimeDomain time_domain = 17; tensorflow.metadata.v0.TimeOfDayDomain time_of_day_domain = 18; } + + // Labels for user defined metadata on feature + map labels=19; } message FeatureSetMeta {