001/* 002 * Copyright (C) 2015-present The Prometheus jmx_exporter Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package io.prometheus.jmx; 018 019import io.prometheus.jmx.common.http.ConfigurationException; 020import io.prometheus.jmx.common.http.HTTPServerFactory; 021import io.prometheus.metrics.exporter.httpserver.HTTPServer; 022import io.prometheus.metrics.instrumentation.jvm.JvmMetrics; 023import io.prometheus.metrics.model.registry.PrometheusRegistry; 024import java.io.File; 025import java.lang.instrument.Instrumentation; 026import java.net.InetAddress; 027import java.util.regex.Matcher; 028import java.util.regex.Pattern; 029 030public class JavaAgent { 031 032 public static final String CONFIGURATION_REGEX = 033 "^(?:((?:[\\w.-]+)|(?:\\[.+])):)?" 034 + // host name, or ipv4, or ipv6 address in brackets 035 "(\\d{1,5}):" 036 + // port 037 "(.+)"; // config file 038 039 private static final String DEFAULT_HOST = "0.0.0.0"; 040 041 private static HTTPServer httpServer; 042 043 public static void agentmain(String agentArgument, Instrumentation instrumentation) 044 throws Exception { 045 premain(agentArgument, instrumentation); 046 } 047 048 public static void premain(String agentArgument, Instrumentation instrumentation) 049 throws Exception { 050 try { 051 Config config = parseConfig(agentArgument); 052 053 new BuildInfoMetrics().register(PrometheusRegistry.defaultRegistry); 054 JvmMetrics.builder().register(PrometheusRegistry.defaultRegistry); 055 new JmxCollector(new File(config.file), JmxCollector.Mode.AGENT) 056 .register(PrometheusRegistry.defaultRegistry); 057 058 String host = config.host != null ? config.host : DEFAULT_HOST; 059 060 httpServer = 061 new HTTPServerFactory() 062 .createHTTPServer( 063 InetAddress.getByName(host), 064 config.port, 065 PrometheusRegistry.defaultRegistry, 066 new File(config.file)); 067 } catch (Throwable t) { 068 synchronized (System.err) { 069 System.err.println("Failed to start Prometheus JMX Exporter"); 070 System.err.println(); 071 t.printStackTrace(); 072 System.err.println(); 073 System.err.println("Prometheus JMX Exporter exiting"); 074 System.err.flush(); 075 } 076 System.exit(1); 077 } 078 } 079 080 /** 081 * Parse the Java Agent configuration. The arguments are typically specified to the JVM as a 082 * javaagent as {@code -javaagent:/path/to/agent.jar=<CONFIG>}. This method parses the {@code 083 * <CONFIG>} portion. 084 * 085 * @param args provided agent args 086 * @return configuration to use for our application 087 */ 088 private static Config parseConfig(String args) { 089 Pattern pattern = Pattern.compile(CONFIGURATION_REGEX); 090 091 Matcher matcher = pattern.matcher(args); 092 if (!matcher.matches()) { 093 System.err.println( 094 "Usage: -javaagent:/path/to/JavaAgent.jar=[host:]<port>:<yaml configuration" 095 + " file> "); 096 throw new ConfigurationException("Malformed arguments - " + args); 097 } 098 099 String givenHost = matcher.group(1); 100 String givenPort = matcher.group(2); 101 String givenConfigFile = matcher.group(3); 102 103 int port = Integer.parseInt(givenPort); 104 105 return new Config(givenHost, port, givenConfigFile); 106 } 107 108 private static class Config { 109 110 String host; 111 int port; 112 String file; 113 114 Config(String host, int port, String file) { 115 this.host = host; 116 this.port = port; 117 this.file = file; 118 } 119 } 120}