Repository: apache/kafka
File: clients/src/main/java/org/apache/kafka/common/utils/AppInfoParser.java (Java)

Code before:
        }
        VERSION = props.getProperty("version", DEFAULT_VALUE).trim();
        COMMIT_ID = props.getProperty("commitId", DEFAULT_VALUE).trim();
    }

    public static String getVersion() {
        return VERSION;
    }

    public static String getCommitId() {
        return COMMIT_ID;
    }

    public static synchronized void registerAppInfo(String prefix, String id, Metrics metrics, long nowMs) {
        try {
            ObjectName name = new ObjectName(prefix + ":type=app-info,id=" + Sanitizer.jmxSanitize(id));
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            if (server.isRegistered(name)) {
                log.info("The mbean of App info: [{}], id: [{}] already exists, so skipping a new mbean creation.", prefix, id);
                return;
            }
            AppInfo mBean = new AppInfo(nowMs);
            server.registerMBean(mBean, name);
            
            registerMetrics(metrics, mBean, null); // prefix will be added later by JmxReporter
            if (!metrics.config().tags().containsKey("client-id")) {
                registerMetrics(metrics, mBean, id);
            }
        } catch (JMException e) {
            log.warn("Error registering AppInfo mbean", e);
        }
    }

    public static synchronized void unregisterAppInfo(String prefix, String id, Metrics metrics) {
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        try {
            ObjectName name = new ObjectName(prefix + ":type=app-info,id=" + Sanitizer.jmxSanitize(id));
            if (server.isRegistered(name))
                server.unregisterMBean(name);

            unregisterMetrics(metrics, null);
            unregisterMetrics(metrics, id);
        } catch (JMException e) {
            log.warn("Error unregistering AppInfo mbean", e);
        } finally {
            log.info("App info {} for {} unregistered", prefix, id);
        }
    }

    private static MetricName metricName(Metrics metrics, String name, Map<String, String> tags) {
        return metrics.metricName(name, "app-info", "Metric indicating " + name, tags);

Review comment (security):
Could you please move this condition into `registerMetrics`? for example:
```java
    public static synchronized void unregisterAppInfo(String prefix, String id, Metrics metrics) {
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        try {
            ObjectName name = new ObjectName(prefix + ":type=app-info,id=" + Sanitizer.jmxSanitize(id));
            if (server.isRegistered(name))
                server.unregisterMBean(name);

            unregisterMetrics(metrics, id);
        } catch (JMException e) {
            log.warn("Error unregistering AppInfo mbean", e);
        } finally {
            log.info("App info {} for {} unregistered", prefix, id);
        }
    }

    private static void registerMetrics(Metrics metrics, AppInfo appInfo, String clientId) {
        if (metrics == null) return;

        // add comments for this case
        metrics.addMetric(metricName(metrics, "version", Map.of()), (Gauge<String>) (config, now) -> appInfo.getVersion());
        metrics.addMetric(metricName(metrics, "commit-id", Map.of()), (Gauge<String>) (config, now) -> appInfo.getCommitId());
        metrics.addMetric(metricName(metrics, "start-time-ms", Map.of()), (Gauge<Long>) (config, now) -> appInfo.getStartTimeMs());

        // add comments for this case
        if (!metrics.config().tags().containsKey("client-id")) {
            metrics.addMetric(metricName(metrics, "version", Map.of("client-id", clientId)), (Gauge<String>) (config, now) -> appInfo.getVersion());
            metrics.addMetric(metricName(metrics, "commit-id", Map.of("client-id", clientId)), (Gauge<String>) (config, now) -> appInfo.getCommitId());
            metrics.addMetric(metricName(metrics, "start-time-ms", Map.of("client-id", clientId)), (Gauge<Long>) (config, now) -> appInfo.getStartTimeMs());
        }
    }

```

Code after:
        }
        VERSION = props.getProperty("version", DEFAULT_VALUE).trim();
        COMMIT_ID = props.getProperty("commitId", DEFAULT_VALUE).trim();
    }

    public static String getVersion() {
        return VERSION;
    }

    public static String getCommitId() {
        return COMMIT_ID;
    }

    public static synchronized void registerAppInfo(String prefix, String id, Metrics metrics, long nowMs) {
        try {
            ObjectName name = new ObjectName(prefix + ":type=app-info,id=" + Sanitizer.jmxSanitize(id));
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            if (server.isRegistered(name)) {
                log.info("The mbean of App info: [{}], id: [{}] already exists, so skipping a new mbean creation.", prefix, id);
                return;
            }
            AppInfo mBean = new AppInfo(nowMs);
            server.registerMBean(mBean, name);

            registerMetrics(metrics, mBean, id); // prefix will be added later by JmxReporter
        } catch (JMException e) {
            log.warn("Error registering AppInfo mbean", e);
        }
    }

    public static synchronized void unregisterAppInfo(String prefix, String id, Metrics metrics) {
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        try {
            ObjectName name = new ObjectName(prefix + ":type=app-info,id=" + Sanitizer.jmxSanitize(id));
            if (server.isRegistered(name))
                server.unregisterMBean(name);

            unregisterMetrics(metrics, id);
        } catch (JMException e) {
            log.warn("Error unregistering AppInfo mbean", e);
        } finally {
            log.info("App info {} for {} unregistered", prefix, id);
        }
    }

    private static MetricName metricName(Metrics metrics, String name, Map<String, String> tags) {
        return metrics.metricName(name, "app-info", "Metric indicating " + name, tags);
    }

    private static void registerMetrics(Metrics metrics, AppInfo appInfo, String clientId) {
        if (metrics == null) return;