class TaggedEventHandler {

   @OnMessage(types = TaggedEvent.NAME)
   public void onTaggedEvent(PlatformMessage msg)
   {
      MessageBody msgBody = msg.getValue();

      String tagName = TaggedEvent.getName(msgBody);

      if (isNotBlank(tagName))
      {
         TaggingMetric<Counter> tagCounter = tagCounterManager.getTagCounter(tagName);

         if (tagCounter != null)
         {
            Map<String, Object> metricTags = TaggedEvent.getContext(msgBody);
            if (metricTags == null)
            {
               metricTags = new HashMap<>();
            }
            else
            {
               // Remove entries with null or blank values from context, since Kairos doesn't like them
               metricTags.entrySet().removeIf(
                  e -> e.getValue() == null || (e.getValue() instanceof String && isBlank((String) e.getValue())));
            }

            // Put in top-level attributes last, so clients can't unintentionally override them via the context

            String source = TaggedEvent.getSource(msgBody);
            if (!isBlank(source))
            {
               metricTags.put(ATTR_SOURCE, source);
            }

            String version = TaggedEvent.getVersion(msgBody);
            if (!isBlank(version))
            {
               metricTags.put(ATTR_VERSION, version);
            }

            String serviceLevel = TaggedEvent.getServiceLevel(msgBody);
            if (!isBlank(serviceLevel))
            {
               metricTags.put(ATTR_SERVICELEVEL, serviceLevel);
            }

            metricTags.keySet().retainAll(contextIncludes);

            tagCounter.tag(metricTags).inc();
         }
         else
         {
            logger.trace("Unknown tag name: " + tagName);

            unknownTagName.inc();
         }
      }
   }

   @Inject public  TaggedEventHandler(TagCounterManager tagCounterManager, TagServiceConfig config);

}