diff --git a/README.md b/README.md index d3f0e04bc..4faf34d07 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ A lightweight & opening Java Agent for Cloud-Native and APM system * Instrumenting the `traceId` and `spanId` into user application logging automatically * Supplying the `health check` endpoint * Supplying the `readiness check` endpoint for `SpringBoot2.2.x` + * Supplying the `agent info` endpoint * Data Reports * Console Reporter. diff --git a/core/pom.xml b/core/pom.xml index cb045ce58..40ec83d95 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -125,6 +125,12 @@ + + + src/main/resources + true + + org.codehaus.mojo diff --git a/core/src/main/java/com/megaease/easeagent/core/Bootstrap.java b/core/src/main/java/com/megaease/easeagent/core/Bootstrap.java index 78c0c6ec8..2cbf0bcb3 100644 --- a/core/src/main/java/com/megaease/easeagent/core/Bootstrap.java +++ b/core/src/main/java/com/megaease/easeagent/core/Bootstrap.java @@ -20,6 +20,7 @@ import com.megaease.easeagent.config.*; import com.megaease.easeagent.context.ContextManager; import com.megaease.easeagent.core.config.*; +import com.megaease.easeagent.core.info.AgentInfoFactory; import com.megaease.easeagent.core.plugin.BaseLoader; import com.megaease.easeagent.core.plugin.BridgeDispatcher; import com.megaease.easeagent.core.plugin.PluginLoader; @@ -32,6 +33,7 @@ import com.megaease.easeagent.plugin.api.trace.TracingProvider; import com.megaease.easeagent.plugin.bean.AgentInitializingBean; import com.megaease.easeagent.plugin.bean.BeanProvider; +import com.megaease.easeagent.plugin.bridge.AgentInfo; import com.megaease.easeagent.plugin.bridge.EaseAgent; import com.megaease.easeagent.plugin.report.AgentReport; import com.megaease.easeagent.report.AgentReportAware; @@ -92,7 +94,10 @@ public static void start(String args, Instrumentation inst) { configPath = args; } - final GlobalConfigs conf = ConfigFactory.loadConfigs(configPath, Bootstrap.class.getClassLoader()); + ClassLoader classLoader = Bootstrap.class.getClassLoader(); + final AgentInfo agentInfo = AgentInfoFactory.loadAgentInfo(classLoader); + EaseAgent.agentInfo = agentInfo; + final GlobalConfigs conf = ConfigFactory.loadConfigs(configPath, classLoader); wrapConfig(conf); // loader check diff --git a/core/src/main/java/com/megaease/easeagent/core/info/AgentInfoFactory.java b/core/src/main/java/com/megaease/easeagent/core/info/AgentInfoFactory.java new file mode 100644 index 000000000..e0d15eefe --- /dev/null +++ b/core/src/main/java/com/megaease/easeagent/core/info/AgentInfoFactory.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021, MegaEase + * All rights reserved. + * + * Licensed 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 com.megaease.easeagent.core.info; + +import com.megaease.easeagent.log4j2.Logger; +import com.megaease.easeagent.log4j2.LoggerFactory; +import com.megaease.easeagent.plugin.bridge.AgentInfo; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class AgentInfoFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(AgentInfoFactory.class); + public static final String AGENT_TYPE = "EaseAgent"; + private static final String VERSION_FILE = "version.txt"; + + + public static AgentInfo loadAgentInfo(ClassLoader classLoader) { + return new AgentInfo(AGENT_TYPE, loadVersion(classLoader, VERSION_FILE)); + } + + + private static String loadVersion(ClassLoader classLoader, String file) { + try (InputStream in = classLoader.getResourceAsStream(file)) { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String version = reader.readLine(); + reader.close(); + return version; + } catch (IOException e) { + LOGGER.warn("Load config file:{} by classloader:{} failure: {}", file, classLoader.toString(), e); + } + return ""; + } +} diff --git a/core/src/main/java/com/megaease/easeagent/core/info/AgentInfoProvider.java b/core/src/main/java/com/megaease/easeagent/core/info/AgentInfoProvider.java new file mode 100644 index 000000000..02ac6300c --- /dev/null +++ b/core/src/main/java/com/megaease/easeagent/core/info/AgentInfoProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021, MegaEase + * All rights reserved. + * + * Licensed 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 com.megaease.easeagent.core.info; + +import com.megaease.easeagent.core.utils.JsonUtil; +import com.megaease.easeagent.httpserver.nano.AgentHttpHandler; +import com.megaease.easeagent.httpserver.nano.AgentHttpHandlerProvider; +import com.megaease.easeagent.httpserver.nano.AgentHttpServer; +import com.megaease.easeagent.httpserver.nanohttpd.protocols.http.IHTTPSession; +import com.megaease.easeagent.httpserver.nanohttpd.protocols.http.response.Response; +import com.megaease.easeagent.httpserver.nanohttpd.protocols.http.response.Status; +import com.megaease.easeagent.httpserver.nanohttpd.router.RouterNanoHTTPD; +import com.megaease.easeagent.plugin.bean.BeanProvider; +import com.megaease.easeagent.plugin.bridge.EaseAgent; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class AgentInfoProvider implements AgentHttpHandlerProvider, BeanProvider { + + @Override + public List getAgentHttpHandlers() { + List list = new ArrayList<>(); + list.add(new AgentInfoHttpHandler()); + return list; + } + + public static class AgentInfoHttpHandler extends AgentHttpHandler { + + @Override + public String getPath() { + return "/agent-info"; + } + + @Override + public Response process(RouterNanoHTTPD.UriResource uriResource, Map urlParams, IHTTPSession session) { + return Response.newFixedLengthResponse(Status.OK, AgentHttpServer.JSON_TYPE, JsonUtil.toJson(EaseAgent.getAgentInfo())); + } + } +} diff --git a/core/src/main/resources/META-INF/services/com.megaease.easeagent.plugin.bean.BeanProvider b/core/src/main/resources/META-INF/services/com.megaease.easeagent.plugin.bean.BeanProvider index 07e000dff..772b7f2a5 100644 --- a/core/src/main/resources/META-INF/services/com.megaease.easeagent.plugin.bean.BeanProvider +++ b/core/src/main/resources/META-INF/services/com.megaease.easeagent.plugin.bean.BeanProvider @@ -1 +1,2 @@ com.megaease.easeagent.core.health.HealthProvider +com.megaease.easeagent.core.info.AgentInfoProvider diff --git a/core/src/main/resources/version.txt b/core/src/main/resources/version.txt new file mode 100644 index 000000000..ad96e7cf9 --- /dev/null +++ b/core/src/main/resources/version.txt @@ -0,0 +1 @@ +${project.version} diff --git a/core/src/test/java/com/megaease/easeagent/core/info/AgentInfoFactoryTest.java b/core/src/test/java/com/megaease/easeagent/core/info/AgentInfoFactoryTest.java new file mode 100644 index 000000000..c3f79ef50 --- /dev/null +++ b/core/src/test/java/com/megaease/easeagent/core/info/AgentInfoFactoryTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, MegaEase + * All rights reserved. + * + * Licensed 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 com.megaease.easeagent.core.info; + +import com.megaease.easeagent.config.ConfigFactory; +import com.megaease.easeagent.config.Configs; +import com.megaease.easeagent.plugin.bridge.AgentInfo; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class AgentInfoFactoryTest { + + @Test + public void loadAgentInfo() { + AgentInfo config = AgentInfoFactory.loadAgentInfo(this.getClass().getClassLoader()); + assertEquals(AgentInfoFactory.AGENT_TYPE, config.getType()); + assertTrue(config.getVersion().matches(".*\\d+\\.\\d+\\.\\d+.*")); + } +} diff --git a/doc/user-manual.md b/doc/user-manual.md index 3e6737477..12038274e 100644 --- a/doc/user-manual.md +++ b/doc/user-manual.md @@ -20,6 +20,7 @@ - [Logging](#logging) - [Prometheus Support](#prometheus-support) - [Health Check and Readiness Check Endpoint](#health-check-and-readiness-check-endpoint) + - [Agent info Endpoint](#agent-info-endpoint) - [Tracing](#tracing) - [Tracing Component](#tracing-component) - [Custom Span Tag](#custom-span-tag) @@ -72,7 +73,7 @@ EaseAgent opens port `9900` by default to receive configuration change notificat | Key | Default Value | Description | | -------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `easeagent.server.enabled` | true | Enable Internal HTTP Server. `false` can disable it. EaseAgent will no longer accept any HTTP requests (`Prometheus`、`Health Check`、`Readiness Check`) when the Internal HTTP Server is disabled. User can add VM parameter:`-Deaseagent.server.enabled=[true or false]` to override. | +| `easeagent.server.enabled` | true | Enable Internal HTTP Server. `false` can disable it. EaseAgent will no longer accept any HTTP requests (`Prometheus`、`Health Check`、`Readiness Check`、`Agent Info`) when the Internal HTTP Server is disabled. User can add VM parameter:`-Deaseagent.server.enabled=[true or false]` to override. | | `easeagent.server.port` | 9900 | Internal HTTP Server port. User can add VM parameter:`-Deaseagent.server.port=[new port]` to override. | #### Output Data Server: Kafka and HTTP/Zipkin Server @@ -384,6 +385,20 @@ After Spring sending `ApplicationReadyEvent`, EaseAgent will change readiness st The response status will be 200(OK) ``` +## Agent info Endpoint +EaseAgent supply the `agent info` http api. +``` +[GET] http://[ip]:[easeagent.server.port]/agent-info +``` +The response status will be 200(OK) +Response Body: +```json +{ + "type": "EaseAgent", + "version": "x.x.x" +} +``` + ## Tracing EaseAgent use [brave](https://github.com/openzipkin/brave) to collect tracing logs.The data format stored in `Kafka` is [Zipkin Data Model](https://zipkin.io/pages/data_model.html). User can send tracing logs to [Zipkin server](https://zipkin.io/pages/quickstart.html). diff --git a/plugin-api/src/main/java/com/megaease/easeagent/plugin/bridge/AgentInfo.java b/plugin-api/src/main/java/com/megaease/easeagent/plugin/bridge/AgentInfo.java new file mode 100644 index 000000000..d22575dd9 --- /dev/null +++ b/plugin-api/src/main/java/com/megaease/easeagent/plugin/bridge/AgentInfo.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, MegaEase + * All rights reserved. + * + * Licensed 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 com.megaease.easeagent.plugin.bridge; + +public class AgentInfo { + private final String type; + private final String version; + + public AgentInfo(String type, String version) { + this.type = type; + this.version = version; + } + + public String getType() { + return type; + } + + public String getVersion() { + return version; + } +} diff --git a/plugin-api/src/main/java/com/megaease/easeagent/plugin/bridge/EaseAgent.java b/plugin-api/src/main/java/com/megaease/easeagent/plugin/bridge/EaseAgent.java index 302429588..bd51b9189 100644 --- a/plugin-api/src/main/java/com/megaease/easeagent/plugin/bridge/EaseAgent.java +++ b/plugin-api/src/main/java/com/megaease/easeagent/plugin/bridge/EaseAgent.java @@ -37,6 +37,7 @@ * the bridge api will be initiated when agent startup */ public final class EaseAgent { + public static AgentInfo agentInfo; public static MetricRegistrySupplier metricRegistrySupplier = NoOpMetrics.NO_OP_METRIC_SUPPLIER; public static IContextManager initializeContextSupplier = () -> NoOpContext.NO_OP_CONTEXT; public static ILoggerFactory loggerFactory = NoOpLoggerFactory.INSTANCE; @@ -136,4 +137,8 @@ public static AutoRefreshPluginConfigImpl getOrCreateAutoRefreshConfig(String do public static Context getContext() { return initializeContextSupplier.getContext(); } + + public static AgentInfo getAgentInfo() { + return agentInfo; + } }