From f8e69a4503377efda88f7c22dd1e92b9b1e291b0 Mon Sep 17 00:00:00 2001 From: "wangjiahua.wjh" Date: Fri, 12 Jun 2026 16:42:31 +0800 Subject: [PATCH 1/2] [ISSUE #10441] Reduce per-RPC allocation in metrics by caching static AttributeKey instances --- .../broker/metrics/BrokerMetricsConstant.java | 19 ++++++ .../broker/metrics/BrokerMetricsManager.java | 68 +++++++++---------- .../broker/metrics/PopMetricsManager.java | 16 ++--- .../metrics/RemotingMetricsConstant.java | 10 +++ .../metrics/RemotingMetricsManager.java | 5 +- 5 files changed, 74 insertions(+), 44 deletions(-) diff --git a/broker/src/main/java/org/apache/rocketmq/broker/metrics/BrokerMetricsConstant.java b/broker/src/main/java/org/apache/rocketmq/broker/metrics/BrokerMetricsConstant.java index 4b319f12f6f..e87ce9ad02d 100644 --- a/broker/src/main/java/org/apache/rocketmq/broker/metrics/BrokerMetricsConstant.java +++ b/broker/src/main/java/org/apache/rocketmq/broker/metrics/BrokerMetricsConstant.java @@ -16,6 +16,8 @@ */ package org.apache.rocketmq.broker.metrics; +import io.opentelemetry.api.common.AttributeKey; + public class BrokerMetricsConstant { public static final String OPEN_TELEMETRY_METER_NAME = "broker-meter"; @@ -64,4 +66,21 @@ public class BrokerMetricsConstant { public static final String LABEL_LANGUAGE = "language"; public static final String LABEL_VERSION = "version"; public static final String LABEL_CONSUME_MODE = "consume_mode"; + + // Pre-built typed AttributeKey singletons. Use these in AttributesBuilder.put() + // on hot paths to avoid allocating a fresh InternalAttributeKeyImpl per call. + public static final AttributeKey LABEL_CLUSTER_NAME_KEY = AttributeKey.stringKey(LABEL_CLUSTER_NAME); + public static final AttributeKey LABEL_NODE_TYPE_KEY = AttributeKey.stringKey(LABEL_NODE_TYPE); + public static final AttributeKey LABEL_NODE_ID_KEY = AttributeKey.stringKey(LABEL_NODE_ID); + public static final AttributeKey LABEL_AGGREGATION_KEY = AttributeKey.stringKey(LABEL_AGGREGATION); + public static final AttributeKey LABEL_PROCESSOR_KEY = AttributeKey.stringKey(LABEL_PROCESSOR); + public static final AttributeKey LABEL_TOPIC_KEY = AttributeKey.stringKey(LABEL_TOPIC); + public static final AttributeKey LABEL_INVOCATION_STATUS_KEY = AttributeKey.stringKey(LABEL_INVOCATION_STATUS); + public static final AttributeKey LABEL_IS_RETRY_KEY = AttributeKey.booleanKey(LABEL_IS_RETRY); + public static final AttributeKey LABEL_IS_SYSTEM_KEY = AttributeKey.booleanKey(LABEL_IS_SYSTEM); + public static final AttributeKey LABEL_CONSUMER_GROUP_KEY = AttributeKey.stringKey(LABEL_CONSUMER_GROUP); + public static final AttributeKey LABEL_MESSAGE_TYPE_KEY = AttributeKey.stringKey(LABEL_MESSAGE_TYPE); + public static final AttributeKey LABEL_LANGUAGE_KEY = AttributeKey.stringKey(LABEL_LANGUAGE); + public static final AttributeKey LABEL_VERSION_KEY = AttributeKey.stringKey(LABEL_VERSION); + public static final AttributeKey LABEL_CONSUME_MODE_KEY = AttributeKey.stringKey(LABEL_CONSUME_MODE); } diff --git a/broker/src/main/java/org/apache/rocketmq/broker/metrics/BrokerMetricsManager.java b/broker/src/main/java/org/apache/rocketmq/broker/metrics/BrokerMetricsManager.java index 835e9e98576..43d0d6141c8 100644 --- a/broker/src/main/java/org/apache/rocketmq/broker/metrics/BrokerMetricsManager.java +++ b/broker/src/main/java/org/apache/rocketmq/broker/metrics/BrokerMetricsManager.java @@ -101,19 +101,19 @@ import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.HISTOGRAM_CONSUMER_GROUP_CREATE_EXECUTE_TIME; import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_AGGREGATION; import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_CLUSTER_NAME; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_CONSUMER_GROUP; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_CONSUME_MODE; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_IS_RETRY; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_IS_SYSTEM; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_LANGUAGE; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_CONSUMER_GROUP_KEY; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_CONSUME_MODE_KEY; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_IS_RETRY_KEY; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_IS_SYSTEM_KEY; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_LANGUAGE_KEY; import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_NODE_ID; import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_NODE_TYPE; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_PROCESSOR; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_TOPIC; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_VERSION; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_PROCESSOR_KEY; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_TOPIC_KEY; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_VERSION_KEY; import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.NODE_TYPE_BROKER; import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.OPEN_TELEMETRY_METER_NAME; -import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.LABEL_PROTOCOL_TYPE; +import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.LABEL_PROTOCOL_TYPE_KEY; import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.PROTOCOL_TYPE_REMOTING; public class BrokerMetricsManager { @@ -197,10 +197,10 @@ public AttributesBuilder newAttributesBuilder() { private Attributes buildLagAttributes(ConsumerLagCalculator.BaseCalculateResult result) { AttributesBuilder attributesBuilder = newAttributesBuilder(); - attributesBuilder.put(LABEL_CONSUMER_GROUP, result.group); - attributesBuilder.put(LABEL_TOPIC, result.topic); - attributesBuilder.put(LABEL_IS_RETRY, result.isRetry); - attributesBuilder.put(LABEL_IS_SYSTEM, isSystem(result.topic, result.group)); + attributesBuilder.put(LABEL_CONSUMER_GROUP_KEY, result.group); + attributesBuilder.put(LABEL_TOPIC_KEY, result.topic); + attributesBuilder.put(LABEL_IS_RETRY_KEY, result.isRetry); + attributesBuilder.put(LABEL_IS_SYSTEM_KEY, isSystem(result.topic, result.group)); return attributesBuilder.build(); } @@ -571,18 +571,18 @@ private void initStatsMetrics() { .setDescription("Request processor watermark") .ofLongs() .buildWithCallback(measurement -> { - measurement.record(brokerController.getSendThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "send").build()); - measurement.record(brokerController.getAsyncPutThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "async_put").build()); - measurement.record(brokerController.getPullThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "pull").build()); - measurement.record(brokerController.getAckThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "ack").build()); - measurement.record(brokerController.getQueryThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "query_message").build()); - measurement.record(brokerController.getClientManagerThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "client_manager").build()); - measurement.record(brokerController.getHeartbeatThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "heartbeat").build()); - measurement.record(brokerController.getLitePullThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "lite_pull").build()); - measurement.record(brokerController.getEndTransactionThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "transaction").build()); - measurement.record(brokerController.getConsumerManagerThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "consumer_manager").build()); - measurement.record(brokerController.getAdminBrokerThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "admin").build()); - measurement.record(brokerController.getReplyThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR, "reply").build()); + measurement.record(brokerController.getSendThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "send").build()); + measurement.record(brokerController.getAsyncPutThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "async_put").build()); + measurement.record(brokerController.getPullThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "pull").build()); + measurement.record(brokerController.getAckThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "ack").build()); + measurement.record(brokerController.getQueryThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "query_message").build()); + measurement.record(brokerController.getClientManagerThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "client_manager").build()); + measurement.record(brokerController.getHeartbeatThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "heartbeat").build()); + measurement.record(brokerController.getLitePullThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "lite_pull").build()); + measurement.record(brokerController.getEndTransactionThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "transaction").build()); + measurement.record(brokerController.getConsumerManagerThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "consumer_manager").build()); + measurement.record(brokerController.getAdminBrokerThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "admin").build()); + measurement.record(brokerController.getReplyThreadPoolQueue().size(), newAttributesBuilder().put(LABEL_PROCESSOR_KEY, "reply").build()); }); brokerPermission = brokerMeter.gaugeBuilder(GAUGE_BROKER_PERMISSION) @@ -662,9 +662,9 @@ private void initConnectionMetrics() { }); metricsMap.forEach((attr, count) -> { Attributes attributes = newAttributesBuilder() - .put(LABEL_LANGUAGE, attr.language.name().toLowerCase()) - .put(LABEL_VERSION, MQVersion.getVersionDesc(attr.version).toLowerCase()) - .put(LABEL_PROTOCOL_TYPE, PROTOCOL_TYPE_REMOTING) + .put(LABEL_LANGUAGE_KEY, attr.language.name().toLowerCase()) + .put(LABEL_VERSION_KEY, MQVersion.getVersionDesc(attr.version).toLowerCase()) + .put(LABEL_PROTOCOL_TYPE_KEY, PROTOCOL_TYPE_REMOTING) .build(); measurement.record(count, attributes); }); @@ -688,12 +688,12 @@ private void initConnectionMetrics() { }); metricsMap.forEach((attr, count) -> { Attributes attributes = newAttributesBuilder() - .put(LABEL_CONSUMER_GROUP, attr.group) - .put(LABEL_LANGUAGE, attr.language.name().toLowerCase()) - .put(LABEL_VERSION, MQVersion.getVersionDesc(attr.version).toLowerCase()) - .put(LABEL_CONSUME_MODE, attr.consumeMode.getTypeCN().toLowerCase()) - .put(LABEL_PROTOCOL_TYPE, PROTOCOL_TYPE_REMOTING) - .put(LABEL_IS_SYSTEM, isSystemGroup(attr.group)) + .put(LABEL_CONSUMER_GROUP_KEY, attr.group) + .put(LABEL_LANGUAGE_KEY, attr.language.name().toLowerCase()) + .put(LABEL_VERSION_KEY, MQVersion.getVersionDesc(attr.version).toLowerCase()) + .put(LABEL_CONSUME_MODE_KEY, attr.consumeMode.getTypeCN().toLowerCase()) + .put(LABEL_PROTOCOL_TYPE_KEY, PROTOCOL_TYPE_REMOTING) + .put(LABEL_IS_SYSTEM_KEY, isSystemGroup(attr.group)) .build(); measurement.record(count, attributes); }); diff --git a/broker/src/main/java/org/apache/rocketmq/broker/metrics/PopMetricsManager.java b/broker/src/main/java/org/apache/rocketmq/broker/metrics/PopMetricsManager.java index 1fb6e892bf6..36a256f2e91 100644 --- a/broker/src/main/java/org/apache/rocketmq/broker/metrics/PopMetricsManager.java +++ b/broker/src/main/java/org/apache/rocketmq/broker/metrics/PopMetricsManager.java @@ -45,8 +45,8 @@ import org.apache.rocketmq.logging.org.slf4j.Logger; import org.apache.rocketmq.logging.org.slf4j.LoggerFactory; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_CONSUMER_GROUP; -import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_TOPIC; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_CONSUMER_GROUP_KEY; +import static org.apache.rocketmq.broker.metrics.BrokerMetricsConstant.LABEL_TOPIC_KEY; import static org.apache.rocketmq.broker.metrics.PopMetricsConstant.COUNTER_POP_REVIVE_IN_MESSAGE_TOTAL; import static org.apache.rocketmq.broker.metrics.PopMetricsConstant.COUNTER_POP_REVIVE_OUT_MESSAGE_TOTAL; import static org.apache.rocketmq.broker.metrics.PopMetricsConstant.COUNTER_POP_REVIVE_RETRY_MESSAGES_TOTAL; @@ -181,8 +181,8 @@ public void incPopReviveCkPutCount(PopCheckPoint checkPoint, PutMessageStatus st public void incPopRevivePutCount(String group, String topic, PopReviveMessageType messageType, PutMessageStatus status, int num) { Attributes attributes = this.newAttributesBuilder() - .put(LABEL_CONSUMER_GROUP, group) - .put(LABEL_TOPIC, topic) + .put(LABEL_CONSUMER_GROUP_KEY, group) + .put(LABEL_TOPIC_KEY, topic) .put(LABEL_REVIVE_MESSAGE_TYPE, messageType.name()) .put(LABEL_PUT_STATUS, status.name()) .build(); @@ -201,8 +201,8 @@ public void incPopReviveGetCount(String group, String topic, PopReviveMessageTyp int num) { AttributesBuilder builder = this.newAttributesBuilder(); Attributes attributes = builder - .put(LABEL_CONSUMER_GROUP, group) - .put(LABEL_TOPIC, topic) + .put(LABEL_CONSUMER_GROUP_KEY, group) + .put(LABEL_TOPIC_KEY, topic) .put(LABEL_QUEUE_ID, queueId) .put(LABEL_REVIVE_MESSAGE_TYPE, messageType.name()) .build(); @@ -212,8 +212,8 @@ public void incPopReviveGetCount(String group, String topic, PopReviveMessageTyp public void incPopReviveRetryMessageCount(PopCheckPoint checkPoint, PutMessageStatus status) { AttributesBuilder builder = this.newAttributesBuilder(); Attributes attributes = builder - .put(LABEL_CONSUMER_GROUP, checkPoint.getCId()) - .put(LABEL_TOPIC, checkPoint.getTopic()) + .put(LABEL_CONSUMER_GROUP_KEY, checkPoint.getCId()) + .put(LABEL_TOPIC_KEY, checkPoint.getTopic()) .put(LABEL_PUT_STATUS, status.name()) .build(); this.popReviveRetryMessageTotal.add(1, attributes); diff --git a/remoting/src/main/java/org/apache/rocketmq/remoting/metrics/RemotingMetricsConstant.java b/remoting/src/main/java/org/apache/rocketmq/remoting/metrics/RemotingMetricsConstant.java index f9b3e4c6fa4..db9999b78f4 100644 --- a/remoting/src/main/java/org/apache/rocketmq/remoting/metrics/RemotingMetricsConstant.java +++ b/remoting/src/main/java/org/apache/rocketmq/remoting/metrics/RemotingMetricsConstant.java @@ -16,6 +16,8 @@ */ package org.apache.rocketmq.remoting.metrics; +import io.opentelemetry.api.common.AttributeKey; + public class RemotingMetricsConstant { public static final String HISTOGRAM_RPC_LATENCY = "rocketmq_rpc_latency"; public static final String LABEL_PROTOCOL_TYPE = "protocol_type"; @@ -24,6 +26,14 @@ public class RemotingMetricsConstant { public static final String LABEL_IS_LONG_POLLING = "is_long_polling"; public static final String LABEL_RESULT = "result"; + // Pre-built typed AttributeKey singletons. Use these in AttributesBuilder.put() + // on hot paths to avoid allocating a fresh InternalAttributeKeyImpl per call. + public static final AttributeKey LABEL_PROTOCOL_TYPE_KEY = AttributeKey.stringKey(LABEL_PROTOCOL_TYPE); + public static final AttributeKey LABEL_REQUEST_CODE_KEY = AttributeKey.stringKey(LABEL_REQUEST_CODE); + public static final AttributeKey LABEL_RESPONSE_CODE_KEY = AttributeKey.stringKey(LABEL_RESPONSE_CODE); + public static final AttributeKey LABEL_IS_LONG_POLLING_KEY = AttributeKey.booleanKey(LABEL_IS_LONG_POLLING); + public static final AttributeKey LABEL_RESULT_KEY = AttributeKey.stringKey(LABEL_RESULT); + public static final String PROTOCOL_TYPE_REMOTING = "remoting"; public static final String RESULT_ONEWAY = "oneway"; diff --git a/remoting/src/main/java/org/apache/rocketmq/remoting/metrics/RemotingMetricsManager.java b/remoting/src/main/java/org/apache/rocketmq/remoting/metrics/RemotingMetricsManager.java index 5da06dcb5ba..09bff2c31e1 100644 --- a/remoting/src/main/java/org/apache/rocketmq/remoting/metrics/RemotingMetricsManager.java +++ b/remoting/src/main/java/org/apache/rocketmq/remoting/metrics/RemotingMetricsManager.java @@ -35,8 +35,9 @@ import org.apache.rocketmq.common.metrics.NopLongHistogram; import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.HISTOGRAM_RPC_LATENCY; -import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.LABEL_PROTOCOL_TYPE; +import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.LABEL_PROTOCOL_TYPE_KEY; import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.PROTOCOL_TYPE_REMOTING; + import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.RESULT_CANCELED; import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.RESULT_SUCCESS; import static org.apache.rocketmq.remoting.metrics.RemotingMetricsConstant.RESULT_WRITE_CHANNEL_FAILED; @@ -53,7 +54,7 @@ public AttributesBuilder newAttributesBuilder() { return Attributes.builder(); } return this.attributesBuilderSupplier.get() - .put(LABEL_PROTOCOL_TYPE, PROTOCOL_TYPE_REMOTING); + .put(LABEL_PROTOCOL_TYPE_KEY, PROTOCOL_TYPE_REMOTING); } public void initMetrics(Meter meter, Supplier attributesBuilderSupplier) { From 077be9584014843a809c081d4af067632cf49577 Mon Sep 17 00:00:00 2001 From: "wangjiahua.wjh" Date: Fri, 12 Jun 2026 16:44:12 +0800 Subject: [PATCH 2/2] [ISSUE #10490] Eliminate per-RPC allocation from Logback status, TopicMessageType toLowerCase, and RemotingHelper eager evaluation --- broker/src/main/resources/rmq.broker.logback.xml | 2 ++ .../apache/rocketmq/common/attribute/TopicMessageType.java | 4 +++- .../org/apache/rocketmq/remoting/common/RemotingHelper.java | 6 ++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/broker/src/main/resources/rmq.broker.logback.xml b/broker/src/main/resources/rmq.broker.logback.xml index 837112837b7..b88bf3a4963 100644 --- a/broker/src/main/resources/rmq.broker.logback.xml +++ b/broker/src/main/resources/rmq.broker.logback.xml @@ -18,6 +18,8 @@ + + brokerContainerLogDir diff --git a/common/src/main/java/org/apache/rocketmq/common/attribute/TopicMessageType.java b/common/src/main/java/org/apache/rocketmq/common/attribute/TopicMessageType.java index 9d3cb7608e5..dec21d096f9 100644 --- a/common/src/main/java/org/apache/rocketmq/common/attribute/TopicMessageType.java +++ b/common/src/main/java/org/apache/rocketmq/common/attribute/TopicMessageType.java @@ -33,9 +33,11 @@ public enum TopicMessageType { MIXED("MIXED"); private final String value; + private final String metricsValue; TopicMessageType(String value) { this.value = value; + this.metricsValue = value.toLowerCase(java.util.Locale.ROOT); } public static Set topicMessageTypeSet() { @@ -67,6 +69,6 @@ public static TopicMessageType parseFromMessageProperty(Map mess } public String getMetricsValue() { - return value.toLowerCase(); + return metricsValue; } } diff --git a/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingHelper.java b/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingHelper.java index 52f7561d719..d80802c5cee 100644 --- a/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingHelper.java +++ b/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingHelper.java @@ -369,10 +369,12 @@ public static CompletableFuture convertChannelFutureToCompletableFuture(Ch } public static String getRequestCodeDesc(int code) { - return REQUEST_CODE_MAP.getOrDefault(code, String.valueOf(code)); + String desc = REQUEST_CODE_MAP.get(code); + return desc != null ? desc : String.valueOf(code); } public static String getResponseCodeDesc(int code) { - return RESPONSE_CODE_MAP.getOrDefault(code, String.valueOf(code)); + String desc = RESPONSE_CODE_MAP.get(code); + return desc != null ? desc : String.valueOf(code); } }