This is an automated email from the ASF dual-hosted git repository.

fanng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new a5169f1d6a [#5901] feat(core): support tag event to Gravitino server 
(#5998)
a5169f1d6a is described below

commit a5169f1d6af9b802d0be90798a631da3b2633b74
Author: TungYu <75083792+tungyuchi...@users.noreply.github.com>
AuthorDate: Mon Mar 3 09:41:51 2025 +0800

    [#5901] feat(core): support tag event to Gravitino server (#5998)
    
    ### What changes were proposed in this pull request?
    
    1. Create corresponding event like ListTagEvent
    2. Add corresponding event to TagEventDispatcher
    
    ### Why are the changes needed?
    
    Fix: #5901
    
    ### Does this PR introduce _any_ user-facing change?
    
    no
    
    ### How was this patch tested?
---
 .../gravitino/listener/TagEventDispatcher.java     |  98 +++++++++++----
 .../listener/api/event/AlterTagEvent.java          |  81 +++++++++++++
 .../event/AssociateTagsForMetadataObjectEvent.java |  94 +++++++++++++++
 .../listener/api/event/CreateTagEvent.java         |  64 ++++++++++
 .../listener/api/event/DeleteTagEvent.java         |  64 ++++++++++
 .../gravitino/listener/api/event/GetTagEvent.java  |  62 ++++++++++
 .../api/event/GetTagForMetadataObjectEvent.java    |  65 ++++++++++
 .../api/event/ListMetadataObjectsForTagEvent.java  |  48 ++++++++
 .../listener/api/event/ListTagsEvent.java          |  48 ++++++++
 .../api/event/ListTagsForMetadataObjectEvent.java  |  51 ++++++++
 .../listener/api/event/ListTagsInfoEvent.java      |  48 ++++++++
 .../event/ListTagsInfoForMetadataObjectEvent.java  |  54 +++++++++
 .../gravitino/listener/api/event/TagEvent.java     |  46 +++++++
 .../gravitino/listener/api/event/TestTagEvent.java | 134 ++++++++++++++++++++-
 docs/gravitino-server-config.md                    |   3 +-
 15 files changed, 929 insertions(+), 31 deletions(-)

diff --git 
a/core/src/main/java/org/apache/gravitino/listener/TagEventDispatcher.java 
b/core/src/main/java/org/apache/gravitino/listener/TagEventDispatcher.java
index c02c4eda65..2dd81cde3f 100644
--- a/core/src/main/java/org/apache/gravitino/listener/TagEventDispatcher.java
+++ b/core/src/main/java/org/apache/gravitino/listener/TagEventDispatcher.java
@@ -21,24 +21,35 @@ package org.apache.gravitino.listener;
 import java.util.Map;
 import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.exceptions.NoSuchTagException;
+import org.apache.gravitino.listener.api.event.AlterTagEvent;
 import org.apache.gravitino.listener.api.event.AlterTagFailureEvent;
 import org.apache.gravitino.listener.api.event.AlterTagPreEvent;
+import 
org.apache.gravitino.listener.api.event.AssociateTagsForMetadataObjectEvent;
 import 
org.apache.gravitino.listener.api.event.AssociateTagsForMetadataObjectFailureEvent;
 import 
org.apache.gravitino.listener.api.event.AssociateTagsForMetadataObjectPreEvent;
+import org.apache.gravitino.listener.api.event.CreateTagEvent;
 import org.apache.gravitino.listener.api.event.CreateTagFailureEvent;
 import org.apache.gravitino.listener.api.event.CreateTagPreEvent;
+import org.apache.gravitino.listener.api.event.DeleteTagEvent;
 import org.apache.gravitino.listener.api.event.DeleteTagFailureEvent;
 import org.apache.gravitino.listener.api.event.DeleteTagPreEvent;
+import org.apache.gravitino.listener.api.event.GetTagEvent;
 import org.apache.gravitino.listener.api.event.GetTagFailureEvent;
+import org.apache.gravitino.listener.api.event.GetTagForMetadataObjectEvent;
 import 
org.apache.gravitino.listener.api.event.GetTagForMetadataObjectFailureEvent;
 import org.apache.gravitino.listener.api.event.GetTagForMetadataObjectPreEvent;
 import org.apache.gravitino.listener.api.event.GetTagPreEvent;
+import org.apache.gravitino.listener.api.event.ListMetadataObjectsForTagEvent;
 import 
org.apache.gravitino.listener.api.event.ListMetadataObjectsForTagFailureEvent;
 import 
org.apache.gravitino.listener.api.event.ListMetadataObjectsForTagPreEvent;
+import org.apache.gravitino.listener.api.event.ListTagsEvent;
 import org.apache.gravitino.listener.api.event.ListTagsFailureEvent;
+import org.apache.gravitino.listener.api.event.ListTagsForMetadataObjectEvent;
 import 
org.apache.gravitino.listener.api.event.ListTagsForMetadataObjectFailureEvent;
 import 
org.apache.gravitino.listener.api.event.ListTagsForMetadataObjectPreEvent;
+import org.apache.gravitino.listener.api.event.ListTagsInfoEvent;
 import org.apache.gravitino.listener.api.event.ListTagsInfoFailureEvent;
+import 
org.apache.gravitino.listener.api.event.ListTagsInfoForMetadataObjectEvent;
 import 
org.apache.gravitino.listener.api.event.ListTagsInfoForMetadataObjectFailureEvent;
 import 
org.apache.gravitino.listener.api.event.ListTagsInfoForMetadataObjectPreEvent;
 import org.apache.gravitino.listener.api.event.ListTagsInfoPreEvent;
@@ -68,8 +79,9 @@ public class TagEventDispatcher implements TagDispatcher {
   public String[] listTags(String metalake) {
     eventBus.dispatchEvent(new 
ListTagsPreEvent(PrincipalUtils.getCurrentUserName(), metalake));
     try {
-      // TODO: listTagsEvent
-      return dispatcher.listTags(metalake);
+      String[] tagNames = dispatcher.listTags(metalake);
+      eventBus.dispatchEvent(new 
ListTagsEvent(PrincipalUtils.getCurrentUserName(), metalake));
+      return tagNames;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new ListTagsFailureEvent(PrincipalUtils.getCurrentUserName(), 
metalake, e));
@@ -81,8 +93,9 @@ public class TagEventDispatcher implements TagDispatcher {
   public Tag[] listTagsInfo(String metalake) {
     eventBus.dispatchEvent(new 
ListTagsInfoPreEvent(PrincipalUtils.getCurrentUserName(), metalake));
     try {
-      // TODO: listTagsInfoEvent
-      return dispatcher.listTagsInfo(metalake);
+      Tag[] tags = dispatcher.listTagsInfo(metalake);
+      eventBus.dispatchEvent(new 
ListTagsInfoEvent(PrincipalUtils.getCurrentUserName(), metalake));
+      return tags;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new ListTagsInfoFailureEvent(PrincipalUtils.getCurrentUserName(), 
metalake, e));
@@ -94,8 +107,11 @@ public class TagEventDispatcher implements TagDispatcher {
   public Tag getTag(String metalake, String name) throws NoSuchTagException {
     eventBus.dispatchEvent(new 
GetTagPreEvent(PrincipalUtils.getCurrentUserName(), metalake, name));
     try {
-      // TODO: getTagEvent
-      return dispatcher.getTag(metalake, name);
+      Tag tag = dispatcher.getTag(metalake, name);
+      TagInfo tagInfo = new TagInfo(tag.name(), tag.comment(), 
tag.properties());
+      eventBus.dispatchEvent(
+          new GetTagEvent(PrincipalUtils.getCurrentUserName(), metalake, name, 
tagInfo));
+      return tag;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new GetTagFailureEvent(PrincipalUtils.getCurrentUserName(), 
metalake, name, e));
@@ -107,13 +123,16 @@ public class TagEventDispatcher implements TagDispatcher {
   public Tag createTag(
       String metalake, String name, String comment, Map<String, String> 
properties) {
     TagInfo tagInfo = new TagInfo(name, comment, properties);
-    // TODO: createTagPreEvent
-
     eventBus.dispatchEvent(
         new CreateTagPreEvent(PrincipalUtils.getCurrentUserName(), metalake, 
tagInfo));
     try {
-      // TODO: createTagEvent
-      return dispatcher.createTag(metalake, name, comment, properties);
+      Tag tag = dispatcher.createTag(metalake, name, comment, properties);
+      eventBus.dispatchEvent(
+          new CreateTagEvent(
+              PrincipalUtils.getCurrentUserName(),
+              metalake,
+              new TagInfo(tag.name(), tag.comment(), tag.properties())));
+      return tag;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new CreateTagFailureEvent(PrincipalUtils.getCurrentUserName(), 
metalake, tagInfo, e));
@@ -128,8 +147,14 @@ public class TagEventDispatcher implements TagDispatcher {
 
     eventBus.dispatchEvent(preEvent);
     try {
-      // TODO: alterTagEvent
-      return dispatcher.alterTag(metalake, name, changes);
+      Tag tag = dispatcher.alterTag(metalake, name, changes);
+      eventBus.dispatchEvent(
+          new AlterTagEvent(
+              PrincipalUtils.getCurrentUserName(),
+              metalake,
+              changes,
+              new TagInfo(tag.name(), tag.comment(), tag.properties())));
+      return tag;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new AlterTagFailureEvent(
@@ -145,8 +170,10 @@ public class TagEventDispatcher implements TagDispatcher {
 
     eventBus.dispatchEvent(preEvent);
     try {
-      // TODO: deleteTagEvent
-      return dispatcher.deleteTag(metalake, name);
+      boolean isExists = dispatcher.deleteTag(metalake, name);
+      eventBus.dispatchEvent(
+          new DeleteTagEvent(PrincipalUtils.getCurrentUserName(), metalake, 
name, isExists));
+      return isExists;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new DeleteTagFailureEvent(PrincipalUtils.getCurrentUserName(), 
metalake, name, e));
@@ -159,8 +186,10 @@ public class TagEventDispatcher implements TagDispatcher {
     eventBus.dispatchEvent(
         new 
ListMetadataObjectsForTagPreEvent(PrincipalUtils.getCurrentUserName(), 
metalake, name));
     try {
-      // TODO: listMetadataObjectsForTagEvent
-      return dispatcher.listMetadataObjectsForTag(metalake, name);
+      MetadataObject[] metadataObjects = 
dispatcher.listMetadataObjectsForTag(metalake, name);
+      eventBus.dispatchEvent(
+          new 
ListMetadataObjectsForTagEvent(PrincipalUtils.getCurrentUserName(), metalake, 
name));
+      return metadataObjects;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new ListMetadataObjectsForTagFailureEvent(
@@ -176,8 +205,11 @@ public class TagEventDispatcher implements TagDispatcher {
             PrincipalUtils.getCurrentUserName(), metalake, metadataObject));
 
     try {
-      // TODO: listTagsForMetadataObjectEvent
-      return dispatcher.listTagsForMetadataObject(metalake, metadataObject);
+      String[] tags = dispatcher.listTagsForMetadataObject(metalake, 
metadataObject);
+      eventBus.dispatchEvent(
+          new ListTagsForMetadataObjectEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, metadataObject));
+      return tags;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new ListTagsForMetadataObjectFailureEvent(
@@ -192,8 +224,11 @@ public class TagEventDispatcher implements TagDispatcher {
         new ListTagsInfoForMetadataObjectPreEvent(
             PrincipalUtils.getCurrentUserName(), metalake, metadataObject));
     try {
-      // TODO: listTagsInfoForMetadataObjectEvent
-      return dispatcher.listTagsInfoForMetadataObject(metalake, 
metadataObject);
+      Tag[] tags = dispatcher.listTagsInfoForMetadataObject(metalake, 
metadataObject);
+      eventBus.dispatchEvent(
+          new ListTagsInfoForMetadataObjectEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, metadataObject));
+      return tags;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new ListTagsInfoForMetadataObjectFailureEvent(
@@ -214,9 +249,18 @@ public class TagEventDispatcher implements TagDispatcher {
             tagsToRemove));
 
     try {
-      // TODO: associateTagsForMetadataObjectEvent
-      return dispatcher.associateTagsForMetadataObject(
-          metalake, metadataObject, tagsToAdd, tagsToRemove);
+      String[] associatedTags =
+          dispatcher.associateTagsForMetadataObject(
+              metalake, metadataObject, tagsToAdd, tagsToRemove);
+      eventBus.dispatchEvent(
+          new AssociateTagsForMetadataObjectEvent(
+              PrincipalUtils.getCurrentUserName(),
+              metalake,
+              metadataObject,
+              tagsToAdd,
+              tagsToRemove,
+              associatedTags));
+      return associatedTags;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new AssociateTagsForMetadataObjectFailureEvent(
@@ -236,8 +280,12 @@ public class TagEventDispatcher implements TagDispatcher {
         new GetTagForMetadataObjectPreEvent(
             PrincipalUtils.getCurrentUserName(), metalake, metadataObject, 
name));
     try {
-      // TODO: getTagForMetadataObjectEvent
-      return dispatcher.getTagForMetadataObject(metalake, metadataObject, 
name);
+      Tag tag = dispatcher.getTagForMetadataObject(metalake, metadataObject, 
name);
+      TagInfo tagInfo = new TagInfo(tag.name(), tag.comment(), 
tag.properties());
+      eventBus.dispatchEvent(
+          new GetTagForMetadataObjectEvent(
+              PrincipalUtils.getCurrentUserName(), metalake, metadataObject, 
tagInfo));
+      return tag;
     } catch (Exception e) {
       eventBus.dispatchEvent(
           new GetTagForMetadataObjectFailureEvent(
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AlterTagEvent.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterTagEvent.java
new file mode 100644
index 0000000000..c3b93aa92a
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterTagEvent.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import javax.annotation.Nullable;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.TagInfo;
+import org.apache.gravitino.tag.TagChange;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event triggered upon the successful alteration of a tag. */
+@DeveloperApi
+public final class AlterTagEvent extends TagEvent {
+  private final TagInfo updatedTagInfo;
+  private final TagChange[] tagChanges;
+
+  /**
+   * Constructs an instance of {@code AlterTagEvent}, encapsulating the key 
details about the
+   * successful alteration of a tag.
+   *
+   * @param user The username of the individual responsible for initiating the 
tag alteration.
+   * @param metalake The metalake from which the tag is being altered.
+   * @param tagChanges An array of {@link TagChange} objects representing the 
specific changes
+   *     applied to the tag during the alteration process.
+   * @param updatedTagInfo The post-alteration state of the tag.
+   */
+  public AlterTagEvent(
+      String user, String metalake, TagChange[] tagChanges, TagInfo 
updatedTagInfo) {
+    super(user, NameIdentifierUtil.ofTag(metalake, updatedTagInfo.name()));
+    this.tagChanges = tagChanges != null ? tagChanges.clone() : null;
+    this.updatedTagInfo = updatedTagInfo;
+  }
+
+  /**
+   * Retrieves the final state of the tag as it was returned to the user after 
successful
+   * alteration.
+   *
+   * @return A {@link TagInfo} instance encapsulating the comprehensive 
details of the newly altered
+   *     tag.
+   */
+  public TagInfo updatedTagInfo() {
+    return updatedTagInfo;
+  }
+
+  /**
+   * Retrieves the specific changes that were made to the tag during the 
alteration process.
+   *
+   * @return An array of {@link TagChange} objects detailing each modification 
applied to the tag.
+   */
+  @Nullable
+  public TagChange[] changes() {
+    return tagChanges;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.ALTER_TAG;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AssociateTagsForMetadataObjectEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AssociateTagsForMetadataObjectEvent.java
new file mode 100644
index 0000000000..7c1bff264f
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AssociateTagsForMetadataObjectEvent.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.MetadataObjectUtil;
+
+/**
+ * Represents an event that is triggered upon successfully associating tags 
with a metadata object.
+ */
+@DeveloperApi
+public final class AssociateTagsForMetadataObjectEvent extends TagEvent {
+  private final String[] tagsToAdd;
+  private final String[] tagsToRemove;
+  private final String[] associatedTags;
+
+  /**
+   * Constructs an instance of {@code AssociateTagsForMetadataObjectEvent}.
+   *
+   * @param user The username of the individual who initiated the tag 
association.
+   * @param metalake The metalake from which the tags were associated.
+   * @param metadataObject The metadata object with which the tags were 
associated.
+   * @param tagsToAdd The tags that were added.
+   * @param tagsToRemove The tags that were removed.
+   * @param associatedTags The resulting list of associated tags after the 
operation.
+   */
+  public AssociateTagsForMetadataObjectEvent(
+      String user,
+      String metalake,
+      MetadataObject metadataObject,
+      String[] tagsToAdd,
+      String[] tagsToRemove,
+      String[] associatedTags) {
+    super(user, MetadataObjectUtil.toEntityIdent(metalake, metadataObject));
+    this.tagsToAdd = tagsToAdd != null ? tagsToAdd.clone() : new String[0];
+    this.tagsToRemove = tagsToRemove != null ? tagsToRemove.clone() : new 
String[0];
+    this.associatedTags = associatedTags != null ? associatedTags.clone() : 
new String[0];
+  }
+
+  /**
+   * Provides the tags that were added in this operation.
+   *
+   * @return An array of tag names that were added.
+   */
+  public String[] tagsToAdd() {
+    return tagsToAdd;
+  }
+
+  /**
+   * Provides the tags that were removed in this operation.
+   *
+   * @return An array of tag names that were removed.
+   */
+  public String[] tagsToRemove() {
+    return tagsToRemove;
+  }
+
+  /**
+   * Provides the resulting list of associated tags after the operation.
+   *
+   * @return An array of tag names representing the associated tags.
+   */
+  public String[] associatedTags() {
+    return associatedTags;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return The operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.ASSOCIATE_TAGS_FOR_METADATA_OBJECT;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/CreateTagEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/CreateTagEvent.java
new file mode 100644
index 0000000000..932190a48b
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/CreateTagEvent.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.TagInfo;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event that is activated upon the successful creation of a 
tag. */
+@DeveloperApi
+public final class CreateTagEvent extends TagEvent {
+  private final TagInfo createdTagInfo;
+
+  /**
+   * Constructs an instance of {@code CreateTagEvent}, capturing essential 
details about the
+   * successful creation of a tag.
+   *
+   * @param user The username of the individual who initiated the tag creation.
+   * @param metalake The metalake from which the tag was created.
+   * @param createdTagInfo The final state of the tag post-creation.
+   */
+  public CreateTagEvent(String user, String metalake, TagInfo createdTagInfo) {
+    super(user, NameIdentifierUtil.ofTag(metalake, createdTagInfo.name()));
+    this.createdTagInfo = createdTagInfo;
+  }
+
+  /**
+   * Provides the final state of the tag as it is presented to the user 
following the successful
+   * creation.
+   *
+   * @return A {@link TagInfo} object that encapsulates the detailed 
characteristics of the newly
+   *     created tag.
+   */
+  public TagInfo createdTagInfo() {
+    return createdTagInfo;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return The operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.CREATE_TAG;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteTagEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteTagEvent.java
new file mode 100644
index 0000000000..4f7ca42f69
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteTagEvent.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event that is generated after a tag is successfully deleted. 
*/
+@DeveloperApi
+public final class DeleteTagEvent extends TagEvent {
+  private final boolean isExists;
+
+  /**
+   * Constructs a new {@code DeleteTagEvent} instance, encapsulating 
information about the outcome
+   * of a tag delete operation.
+   *
+   * @param user The user who initiated the delete tag operation.
+   * @param metalake The metalake from which the tag was deleted.
+   * @param name The name of the tag.
+   * @param isExists A boolean flag indicating whether the tag existed at the 
time of the delete
+   *     operation.
+   */
+  public DeleteTagEvent(String user, String metalake, String name, boolean 
isExists) {
+    super(user, NameIdentifierUtil.ofTag(metalake, name));
+    this.isExists = isExists;
+  }
+
+  /**
+   * Retrieves the existence status of the tag at the time of the delete 
operation.
+   *
+   * @return A boolean value indicating whether the tag existed. {@code true} 
if the tag existed,
+   *     otherwise {@code false}.
+   */
+  public boolean isExists() {
+    return isExists;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.DELETE_TAG;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagEvent.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagEvent.java
new file mode 100644
index 0000000000..8cd4504ee6
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagEvent.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.TagInfo;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event that is triggered upon successfully retrieving a tag. 
*/
+@DeveloperApi
+public final class GetTagEvent extends TagEvent {
+  private final TagInfo tagInfo;
+
+  /**
+   * Constructs an instance of {@code GetTagEvent}.
+   *
+   * @param user The username of the individual who initiated the tag 
retrieval.
+   * @param metalake The metalake from which the tag was retrieved.
+   * @param tagName The name of the tag being retrieved.
+   * @param tagInfo The {@link TagInfo} object representing the retrieved tag.
+   */
+  public GetTagEvent(String user, String metalake, String tagName, TagInfo 
tagInfo) {
+    super(user, NameIdentifierUtil.ofTag(metalake, tagName));
+    this.tagInfo = tagInfo;
+  }
+
+  /**
+   * Returns the {@link TagInfo} object representing the retrieved tag.
+   *
+   * @return The tag information.
+   */
+  public TagInfo tagInfo() {
+    return tagInfo;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return The operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.GET_TAG;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagForMetadataObjectEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagForMetadataObjectEvent.java
new file mode 100644
index 0000000000..01d39c0c78
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagForMetadataObjectEvent.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.TagInfo;
+import org.apache.gravitino.utils.MetadataObjectUtil;
+
+/**
+ * Represents an event that is triggered upon successfully retrieving a tag 
for a metadata object.
+ */
+@DeveloperApi
+public final class GetTagForMetadataObjectEvent extends TagEvent {
+  private final TagInfo tagInfo;
+  /**
+   * Constructs an instance of {@code GetTagForMetadataObjectEvent}.
+   *
+   * @param user The username of the individual who initiated the tag 
retrieval.
+   * @param metalake The metalake from which the tag was retrieved.
+   * @param metadataObject The metadata object for which the tag was retrieved.
+   * @param tagInfo The {@link TagInfo} object representing the retrieved tag.
+   */
+  public GetTagForMetadataObjectEvent(
+      String user, String metalake, MetadataObject metadataObject, TagInfo 
tagInfo) {
+    super(user, MetadataObjectUtil.toEntityIdent(metalake, metadataObject));
+    this.tagInfo = tagInfo;
+  }
+
+  /**
+   * Returns the {@link TagInfo} object representing the retrieved tag.
+   *
+   * @return The tag information.
+   */
+  public TagInfo tagInfo() {
+    return tagInfo;
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return The operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.GET_TAG_FOR_METADATA_OBJECT;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListMetadataObjectsForTagEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListMetadataObjectsForTagEvent.java
new file mode 100644
index 0000000000..0e8a7e072e
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListMetadataObjectsForTagEvent.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event that is triggered upon successfully listing metadata 
objects for a tag. */
+@DeveloperApi
+public final class ListMetadataObjectsForTagEvent extends TagEvent {
+  /**
+   * Constructs an instance of {@code ListMetadataObjectsForTagEvent}.
+   *
+   * @param user The username of the individual who initiated the metadata 
objects listing.
+   * @param metalake The metalake from which metadata objects were listed.
+   * @param tagName The name of the tag for which metadata objects were listed.
+   */
+  public ListMetadataObjectsForTagEvent(String user, String metalake, String 
tagName) {
+    super(user, NameIdentifierUtil.ofTag(metalake, tagName));
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return The operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.LIST_METADATA_OBJECTS_FOR_TAG;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsEvent.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsEvent.java
new file mode 100644
index 0000000000..dd19f00fe3
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsEvent.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents an event that is triggered upon the successful listing of tags. 
*/
+@DeveloperApi
+public final class ListTagsEvent extends TagEvent {
+
+  /**
+   * Constructs an instance of {@code ListTagEvent}.
+   *
+   * @param user The username of the individual who initiated the tag listing.
+   * @param metalake The namespace from which tags were listed.
+   */
+  public ListTagsEvent(String user, String metalake) {
+    super(user, NameIdentifier.of(metalake));
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.LIST_TAG;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsForMetadataObjectEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsForMetadataObjectEvent.java
new file mode 100644
index 0000000000..598c71cb08
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsForMetadataObjectEvent.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.MetadataObjectUtil;
+
+/** Represents an event that is triggered upon successfully listing tags for a 
metadata object. */
+@DeveloperApi
+public final class ListTagsForMetadataObjectEvent extends TagEvent {
+
+  /**
+   * Constructs an instance of {@code ListTagsForMetadataObjectEvent}.
+   *
+   * @param user The username of the individual who initiated the tag listing.
+   * @param metalake The metalake from which tags were listed.
+   * @param metadataObject The metadata object for which tags were listed.
+   */
+  public ListTagsForMetadataObjectEvent(
+      String user, String metalake, MetadataObject metadataObject) {
+    super(user, MetadataObjectUtil.toEntityIdent(metalake, metadataObject));
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return The operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.LIST_TAGS_FOR_METADATA_OBJECT;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoEvent.java
new file mode 100644
index 0000000000..13126671f6
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoEvent.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents an event that is triggered upon the successful listing of tags. 
*/
+@DeveloperApi
+public final class ListTagsInfoEvent extends TagEvent {
+
+  /**
+   * Constructs an instance of {@code ListTagsEvent}.
+   *
+   * @param user The username of the individual who initiated the tag listing.
+   * @param metalake The namespace from which tags were listed.
+   */
+  public ListTagsInfoEvent(String user, String metalake) {
+    super(user, NameIdentifier.of(metalake));
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.LIST_TAGS_INFO;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoForMetadataObjectEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoForMetadataObjectEvent.java
new file mode 100644
index 0000000000..e41244bd1f
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoForMetadataObjectEvent.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.MetadataObjectUtil;
+
+/**
+ * Represents an event that is triggered upon successfully listing detailed 
tag information for a
+ * metadata object.
+ */
+@DeveloperApi
+public final class ListTagsInfoForMetadataObjectEvent extends TagEvent {
+
+  /**
+   * Constructs an instance of {@code ListTagsInfoForMetadataObjectEvent}.
+   *
+   * @param user The username of the individual who initiated the tag 
information listing.
+   * @param metalake The metalake from which tag information was listed.
+   * @param metadataObject The metadata object for which tag information was 
listed.
+   */
+  public ListTagsInfoForMetadataObjectEvent(
+      String user, String metalake, MetadataObject metadataObject) {
+    super(user, MetadataObjectUtil.toEntityIdent(metalake, metadataObject));
+  }
+
+  /**
+   * Returns the type of operation.
+   *
+   * @return The operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.LIST_TAGS_INFO_FOR_METADATA_OBJECT;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/TagEvent.java 
b/core/src/main/java/org/apache/gravitino/listener/api/event/TagEvent.java
new file mode 100644
index 0000000000..e7f59ca988
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/listener/api/event/TagEvent.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/**
+ * Represents an abstract base class for events related to tag operations. 
This class extends {@link
+ * Event} to provide a more specific context involving operations on tags, 
such as creation,
+ * deletion, or modification.
+ */
+@DeveloperApi
+public abstract class TagEvent extends Event {
+  /**
+   * Constructs a new {@code TagEvent} with the specified user and tag 
identifier.
+   *
+   * @param user The user responsible for triggering the tag operation.
+   * @param identifier The identifier of the tag involved in the operation.
+   */
+  protected TagEvent(String user, NameIdentifier identifier) {
+    super(user, identifier);
+  }
+
+  @Override
+  public OperationStatus operationStatus() {
+    return OperationStatus.SUCCESS;
+  }
+}
diff --git 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestTagEvent.java 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestTagEvent.java
index 2eaa2a5a41..8a59f406d3 100644
--- 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestTagEvent.java
+++ 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestTagEvent.java
@@ -19,11 +19,13 @@
 
 package org.apache.gravitino.listener.api.event;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import com.google.common.collect.ImmutableMap;
 import java.util.Arrays;
+import java.util.Map;
 import java.util.Objects;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.MetadataObject;
@@ -71,6 +73,12 @@ public class TestTagEvent {
     Assertions.assertEquals(ListTagsPreEvent.class, preEvent.getClass());
     Assertions.assertEquals(OperationType.LIST_TAG, preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals("metalake", 
Objects.requireNonNull(postevent.identifier()).toString());
+    Assertions.assertEquals(ListTagsEvent.class, postevent.getClass());
+    Assertions.assertEquals(OperationType.LIST_TAG, postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
   }
 
   @Test
@@ -82,6 +90,12 @@ public class TestTagEvent {
     Assertions.assertEquals(ListTagsInfoPreEvent.class, preEvent.getClass());
     Assertions.assertEquals(OperationType.LIST_TAGS_INFO, 
preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals("metalake", 
Objects.requireNonNull(postevent.identifier()).toString());
+    Assertions.assertEquals(ListTagsInfoEvent.class, postevent.getClass());
+    Assertions.assertEquals(OperationType.LIST_TAGS_INFO, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
   }
 
   @Test
@@ -94,6 +108,15 @@ public class TestTagEvent {
     Assertions.assertEquals(GetTagPreEvent.class, preEvent.getClass());
     Assertions.assertEquals(OperationType.GET_TAG, preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(GetTagEvent.class, postevent.getClass());
+    Assertions.assertEquals(OperationType.GET_TAG, postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
+    TagInfo tagInfo = ((GetTagEvent) postevent).tagInfo();
+    checkTagInfo(tagInfo, tag);
   }
 
   @Test
@@ -106,12 +129,18 @@ public class TestTagEvent {
     Assertions.assertEquals(CreateTagPreEvent.class, preEvent.getClass());
 
     TagInfo tagInfo = ((CreateTagPreEvent) preEvent).tagInfo();
-    Assertions.assertEquals(tag.name(), tagInfo.name());
-    Assertions.assertEquals(tag.properties(), tagInfo.properties());
-    Assertions.assertEquals(tag.comment(), tagInfo.comment());
+    checkTagInfo(tagInfo, tag);
 
     Assertions.assertEquals(OperationType.CREATE_TAG, 
preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(CreateTagEvent.class, postevent.getClass());
+    TagInfo tagInfo2 = ((CreateTagEvent) postevent).createdTagInfo();
+    checkTagInfo(tagInfo2, tag);
+    Assertions.assertEquals(OperationType.CREATE_TAG, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
   }
 
   @Test
@@ -130,6 +159,15 @@ public class TestTagEvent {
 
     TagChange[] eventChanges = ((AlterTagPreEvent) preEvent).changes();
     Assertions.assertArrayEquals(changes, eventChanges);
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(AlterTagEvent.class, postevent.getClass());
+    Assertions.assertEquals(OperationType.ALTER_TAG, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
+
+    TagChange[] postChanges = ((AlterTagEvent) postevent).changes();
+    Assertions.assertArrayEquals(changes, postChanges);
   }
 
   @Test
@@ -142,6 +180,12 @@ public class TestTagEvent {
     Assertions.assertEquals(DeleteTagPreEvent.class, preEvent.getClass());
     Assertions.assertEquals(OperationType.DELETE_TAG, 
preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(DeleteTagEvent.class, postevent.getClass());
+    Assertions.assertEquals(OperationType.DELETE_TAG, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
   }
 
   @Test
@@ -154,6 +198,12 @@ public class TestTagEvent {
     Assertions.assertEquals(ListMetadataObjectsForTagPreEvent.class, 
preEvent.getClass());
     Assertions.assertEquals(OperationType.LIST_METADATA_OBJECTS_FOR_TAG, 
preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(ListMetadataObjectsForTagEvent.class, 
postevent.getClass());
+    Assertions.assertEquals(OperationType.LIST_METADATA_OBJECTS_FOR_TAG, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
   }
 
   @Test
@@ -171,6 +221,12 @@ public class TestTagEvent {
     Assertions.assertEquals(ListTagsForMetadataObjectPreEvent.class, 
preEvent.getClass());
     Assertions.assertEquals(OperationType.LIST_TAGS_FOR_METADATA_OBJECT, 
preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(ListTagsForMetadataObjectEvent.class, 
postevent.getClass());
+    Assertions.assertEquals(OperationType.LIST_TAGS_FOR_METADATA_OBJECT, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
   }
 
   @Test
@@ -189,6 +245,13 @@ public class TestTagEvent {
     Assertions.assertEquals(
         OperationType.LIST_TAGS_INFO_FOR_METADATA_OBJECT, 
preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(ListTagsInfoForMetadataObjectEvent.class, 
postevent.getClass());
+    Assertions.assertEquals(
+        OperationType.LIST_TAGS_INFO_FOR_METADATA_OBJECT, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
   }
 
   @Test
@@ -216,6 +279,17 @@ public class TestTagEvent {
     Assertions.assertEquals(
         OperationType.ASSOCIATE_TAGS_FOR_METADATA_OBJECT, 
preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(AssociateTagsForMetadataObjectEvent.class, 
postevent.getClass());
+    Assertions.assertArrayEquals(
+        tagsToAdd, ((AssociateTagsForMetadataObjectEvent) 
postevent).tagsToAdd());
+    Assertions.assertArrayEquals(
+        tagsToRemove, ((AssociateTagsForMetadataObjectEvent) 
postevent).tagsToRemove());
+    Assertions.assertEquals(
+        OperationType.ASSOCIATE_TAGS_FOR_METADATA_OBJECT, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
   }
 
   @Test
@@ -235,6 +309,15 @@ public class TestTagEvent {
     Assertions.assertEquals(tag.name(), ((GetTagForMetadataObjectPreEvent) 
preEvent).tagName());
     Assertions.assertEquals(OperationType.GET_TAG_FOR_METADATA_OBJECT, 
preEvent.operationType());
     Assertions.assertEquals(OperationStatus.UNPROCESSED, 
preEvent.operationStatus());
+
+    Event postevent = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(identifier.toString(), 
postevent.identifier().toString());
+    Assertions.assertEquals(GetTagForMetadataObjectEvent.class, 
postevent.getClass());
+    Assertions.assertEquals(OperationType.GET_TAG_FOR_METADATA_OBJECT, 
postevent.operationType());
+    Assertions.assertEquals(OperationStatus.SUCCESS, 
postevent.operationStatus());
+
+    TagInfo tagInfo = ((GetTagForMetadataObjectEvent) postevent).tagInfo();
+    checkTagInfo(tagInfo, tag);
   }
 
   @Test
@@ -424,8 +507,49 @@ public class TestTagEvent {
         });
   }
 
+  private void checkTagInfo(TagInfo actualTagInfo, Tag expectedTag) {
+    Assertions.assertEquals(expectedTag.name(), actualTagInfo.name());
+    Assertions.assertEquals(expectedTag.comment(), actualTagInfo.comment());
+    Assertions.assertEquals(expectedTag.properties(), 
actualTagInfo.properties());
+  }
+
   private TagDispatcher mockTagDispatcher() {
-    TagDispatcher mockDispatcher = mock(TagDispatcher.class);
-    return mockDispatcher;
+    TagDispatcher dispatcher = mock(TagDispatcher.class);
+    String metalake = "metalake";
+    String[] tagNames = new String[] {"tag1", "tag2"};
+    Tag[] tags = new Tag[] {tag, tag};
+
+    when(dispatcher.createTag(
+            any(String.class), any(String.class), any(String.class), 
any(Map.class)))
+        .thenReturn(tag);
+    when(dispatcher.listTags(metalake)).thenReturn(tagNames);
+    when(dispatcher.listTagsInfo(metalake)).thenReturn(tags);
+    when(dispatcher.alterTag(any(String.class), any(String.class), 
any(TagChange[].class)))
+        .thenReturn(tag);
+    when(dispatcher.getTag(any(String.class), 
any(String.class))).thenReturn(tag);
+    when(dispatcher.deleteTag(metalake, tag.name())).thenReturn(true);
+    when(dispatcher.getTagForMetadataObject(
+            any(String.class), any(MetadataObject.class), any(String.class)))
+        .thenReturn(tag);
+    MetadataObject catalog =
+        NameIdentifierUtil.toMetadataObject(
+            NameIdentifierUtil.ofCatalog("metalake", "catalog_for_test"),
+            Entity.EntityType.CATALOG);
+    MetadataObject[] objects = new MetadataObject[] {catalog};
+
+    when(dispatcher.listMetadataObjectsForTag(any(String.class), 
any(String.class)))
+        .thenReturn(objects);
+
+    when(dispatcher.associateTagsForMetadataObject(
+            any(String.class), any(MetadataObject.class), any(String[].class), 
any(String[].class)))
+        .thenReturn(new String[] {"tag1", "tag2"});
+
+    when(dispatcher.listTagsForMetadataObject(any(String.class), 
any(MetadataObject.class)))
+        .thenReturn(new String[] {"tag1", "tag2"});
+
+    when(dispatcher.listTagsInfoForMetadataObject(any(String.class), 
any(MetadataObject.class)))
+        .thenReturn(new Tag[] {tag, tag});
+
+    return dispatcher;
   }
 }
diff --git a/docs/gravitino-server-config.md b/docs/gravitino-server-config.md
index bdcb03a939..88edf23470 100644
--- a/docs/gravitino-server-config.md
+++ b/docs/gravitino-server-config.md
@@ -125,7 +125,7 @@ Gravitino triggers a pre-event before the operation, a 
post-event after the comp
 | catalog operation                   | `CreateCatalogEvent`, 
`AlterCatalogEvent`, `DropCatalogEvent`, `LoadCatalogEvent`, 
`ListCatalogEvent`, `CreateCatalogFailureEvent`, `AlterCatalogFailureEvent`, 
`DropCatalogFailureEvent`, `LoadCatalogFailureEvent`, `ListCatalogFailureEvent` 
                                                                                
                                                                                
              | 0.5.0            |
 | metalake operation                  | `CreateMetalakeEvent`, 
`AlterMetalakeEvent`, `DropMetalakeEvent`, `LoadMetalakeEvent`, 
`ListMetalakeEvent`, `CreateMetalakeFailureEvent`, `AlterMetalakeFailureEvent`, 
`DropMetalakeFailureEvent`, `LoadMetalakeFailureEvent`, 
`ListMetalakeFailureEvent`                                                      
                                                                                
                               | 0.5.0            |
 | Iceberg REST server table operation | `IcebergCreateTableEvent`, 
`IcebergUpdateTableEvent`, `IcebergDropTableEvent`, `IcebergLoadTableEvent`, 
`IcebergListTableEvent`, `IcebergTableExistsEvent`, `IcebergRenameTableEvent`, 
`IcebergCreateTableFailureEvent`, `IcebergUpdateTableFailureEvent`, 
`IcebergDropTableFailureEvent`, `IcebergLoadTableFailureEvent`, 
`IcebergListTableFailureEvent`, `IcebergRenameTableFailureEvent`, 
`IcebergTableExistsFailureEvent` | 0.7.0-incubating |
-| tag operation                       | `ListTagsFailureEvent`, 
`ListTagInfoFailureEvent`, `CreateTagFailureEvent`, `GetTagFailureEvent`, 
`AlterTagFailureEvent`, `DeleteTagFailureEvent`, 
`ListMetadataObjectsForTagFailureEvent`, 
`ListTagsForMetadataObjectFailureEvent`, 
`ListTagsInfoForMetadataObjectFailureEvent`, 
`AssociateTagsForMetadataObjectFailureEvent`, 
`GetTagForMetadataObjectFailureEvent`                                           
                                                     [...]
+| tag operation                       | `ListTagsEvent`, `ListTagsInfoEvent`, 
`CreateTagEvent`, `GetTagEvent`, `AlterTagEvent`, `DeleteTagEvent`, 
`ListMetadataObjectsForTagEvent`, `ListTagsForMetadataObjectEvent`, 
`ListTagsInfoForMetadataObjectEvent`, `AssociateTagsForMetadataObjectEvent`, 
`GetTagForMetadataObjectEvent`, `ListTagsFailureEvent`, 
`ListTagInfoFailureEvent`, `CreateTagFailureEvent`, `GetTagFailureEvent`, 
`AlterTagFailureEvent`, `DeleteTagFailureEvent`, `ListMetadataObjectsFo [...]
 
 ##### Pre-event
 
@@ -138,6 +138,7 @@ Gravitino triggers a pre-event before the operation, a 
post-event after the comp
 | Gravitino server metalake operation  | `CreateMetalakePreEvent`, 
`AlterMetalakePreEvent`,`DropMetalakePreEvent`,`LoadMetalakePreEvent`,`ListMetalakePreEvent`
                                                                                
    | 0.8.0-incubating |
 | Gravitino server partition operation | `AddPartitionPreEvent`, 
`DropPartitionPreEvent`, `GetPartitionPreEvent`, 
`PurgePartitionPreEvent`,`ListPartitionPreEvent`,`ListPartitionNamesPreEvent`   
                                                 | 0.8.0-incubating |
 | Gravitino server fileset operation   | `CreateFilesetPreEvent`, 
`AlterFilesetPreEvent`, `DropFilesetPreEvent`, 
`LoadFilesetPreEvent`,`ListFilesetPreEvent`,`GetFileLocationPreEvent`           
                                                  | 0.8.0-incubating |
+| Gravitino server tag operation       | `ListTagsPreEvent`, 
`ListTagsInfoPreEvent`, `CreateTagPreEvent`, `GetTagPreEvent`, 
`AlterTagPreEvent`, `DeleteTagPreEvent`, `ListMetadataObjectsForTagPreEvent`, 
`ListTagsForMetadataObjectPreEvent`, `ListTagsInfoForMetadataObjectPreEvent`, 
`AssociateTagsForMetadataObjectPreEvent`, `GetTagForMetadataObjectPreEvent` | 
0.9.0-incubating |
 
 #### Event listener plugin
 

Reply via email to