-
Notifications
You must be signed in to change notification settings - Fork 199
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Copy in azure monitor opentelemetry exporter * more * sync * remove * checkstyle
- Loading branch information
Showing
106 changed files
with
4,711 additions
and
644 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
313 changes: 313 additions & 0 deletions
313
...g/src/main/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExporterBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,313 @@ | ||
/* | ||
* ApplicationInsights-Java | ||
* Copyright (c) Microsoft Corporation | ||
* All rights reserved. | ||
* | ||
* MIT License | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this | ||
* software and associated documentation files (the ""Software""), to deal in the Software | ||
* without restriction, including without limitation the rights to use, copy, modify, merge, | ||
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit | ||
* persons to whom the Software is furnished to do so, subject to the following conditions: | ||
* The above copyright notice and this permission notice shall be included in all copies or | ||
* substantial portions of the Software. | ||
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE | ||
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
* DEALINGS IN THE SOFTWARE. | ||
*/ | ||
|
||
package com.azure.monitor.opentelemetry.exporter; | ||
|
||
import com.azure.core.credential.TokenCredential; | ||
import com.azure.core.http.HttpClient; | ||
import com.azure.core.http.HttpPipeline; | ||
import com.azure.core.http.policy.BearerTokenAuthenticationPolicy; | ||
import com.azure.core.http.policy.HttpLogDetailLevel; | ||
import com.azure.core.http.policy.HttpLogOptions; | ||
import com.azure.core.http.policy.HttpPipelinePolicy; | ||
import com.azure.core.http.policy.RetryPolicy; | ||
import com.azure.core.util.ClientOptions; | ||
import com.azure.core.util.Configuration; | ||
import com.azure.core.util.logging.ClientLogger; | ||
import com.azure.core.util.serializer.JacksonAdapter; | ||
import com.azure.core.util.serializer.SerializerAdapter; | ||
import com.azure.monitor.opentelemetry.exporter.implementation.ApplicationInsightsClientImpl; | ||
import com.azure.monitor.opentelemetry.exporter.implementation.ApplicationInsightsClientImplBuilder; | ||
import com.azure.monitor.opentelemetry.exporter.implementation.NdJsonSerializer; | ||
import com.fasterxml.jackson.databind.module.SimpleModule; | ||
import io.opentelemetry.sdk.trace.export.SpanExporter; | ||
import java.net.MalformedURLException; | ||
import java.net.URL; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
/** | ||
* This class provides a fluent builder API to instantiate {@link AzureMonitorTraceExporter} that | ||
* implements {@link SpanExporter} interface defined by OpenTelemetry API specification. | ||
*/ | ||
public final class AzureMonitorExporterBuilder { | ||
private static final String APPLICATIONINSIGHTS_CONNECTION_STRING = | ||
"APPLICATIONINSIGHTS_CONNECTION_STRING"; | ||
private static final String APPLICATIONINSIGHTS_AUTHENTICATION_SCOPE = | ||
"https://monitor.azure.com//.default"; | ||
private static final SerializerAdapter SERIALIZER_ADAPTER; | ||
private final ClientLogger logger = new ClientLogger(AzureMonitorExporterBuilder.class); | ||
private final ApplicationInsightsClientImplBuilder restServiceClientBuilder; | ||
private String instrumentationKey; | ||
private String connectionString; | ||
|
||
// suppress warnings is needed in ApplicationInsights-Java repo, can be removed when upstreaming | ||
@SuppressWarnings({"UnusedVariable", "FieldCanBeLocal"}) | ||
private AzureMonitorExporterServiceVersion serviceVersion; | ||
|
||
private TokenCredential credential; | ||
|
||
static { | ||
// Customize serializer to use NDJSON | ||
final SimpleModule ndjsonModule = new SimpleModule("Ndjson List Serializer"); | ||
JacksonAdapter jacksonAdapter = new JacksonAdapter(); | ||
ndjsonModule.addSerializer(new NdJsonSerializer()); | ||
jacksonAdapter.serializer().registerModule(ndjsonModule); | ||
|
||
SERIALIZER_ADAPTER = jacksonAdapter; | ||
} | ||
|
||
/** Creates an instance of {@link AzureMonitorExporterBuilder}. */ | ||
public AzureMonitorExporterBuilder() { | ||
restServiceClientBuilder = new ApplicationInsightsClientImplBuilder(); | ||
} | ||
|
||
/** | ||
* Sets the service endpoint for the Azure Monitor Exporter. | ||
* | ||
* @param endpoint The URL of the Azure Monitor Exporter endpoint. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
* @throws NullPointerException if {@code endpoint} is null. | ||
* @throws IllegalArgumentException if {@code endpoint} cannot be parsed into a valid URL. | ||
*/ | ||
AzureMonitorExporterBuilder endpoint(String endpoint) { | ||
Objects.requireNonNull(endpoint, "'endpoint' cannot be null."); | ||
try { | ||
URL url = new URL(endpoint); | ||
restServiceClientBuilder.host(url.getProtocol() + "://" + url.getHost()); | ||
} catch (MalformedURLException ex) { | ||
throw logger.logExceptionAsWarning( | ||
new IllegalArgumentException("'endpoint' must be a valid URL.", ex)); | ||
} | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the HTTP pipeline to use for the service client. If {@code pipeline} is set, all other | ||
* settings are ignored, apart from {@link #endpoint(String) endpoint}. | ||
* | ||
* @param httpPipeline The HTTP pipeline to use for sending service requests and receiving | ||
* responses. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
*/ | ||
public AzureMonitorExporterBuilder pipeline(HttpPipeline httpPipeline) { | ||
restServiceClientBuilder.pipeline(httpPipeline); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the HTTP client to use for sending and receiving requests to and from the service. | ||
* | ||
* @param client The HTTP client to use for requests. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
*/ | ||
public AzureMonitorExporterBuilder httpClient(HttpClient client) { | ||
restServiceClientBuilder.httpClient(client); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the logging configuration for HTTP requests and responses. | ||
* | ||
* <p>If logLevel is not provided, default value of {@link HttpLogDetailLevel#NONE} is set. | ||
* | ||
* @param logOptions The logging configuration to use when sending and receiving HTTP | ||
* requests/responses. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
*/ | ||
public AzureMonitorExporterBuilder httpLogOptions(HttpLogOptions logOptions) { | ||
restServiceClientBuilder.httpLogOptions(logOptions); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the {@link RetryPolicy} that is used when each request is sent. | ||
* | ||
* <p>The default retry policy will be used if not provided to build {@link | ||
* AzureMonitorExporterBuilder} . | ||
* | ||
* @param retryPolicy user's retry policy applied to each request. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
*/ | ||
public AzureMonitorExporterBuilder retryPolicy(RetryPolicy retryPolicy) { | ||
restServiceClientBuilder.retryPolicy(retryPolicy); | ||
return this; | ||
} | ||
|
||
/** | ||
* Adds a policy to the set of existing policies that are executed after required policies. | ||
* | ||
* @param policy The retry policy for service requests. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
* @throws NullPointerException If {@code policy} is {@code null}. | ||
*/ | ||
public AzureMonitorExporterBuilder addPolicy(HttpPipelinePolicy policy) { | ||
restServiceClientBuilder.addPolicy(Objects.requireNonNull(policy, "'policy' cannot be null.")); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the configuration store that is used during construction of the service client. | ||
* | ||
* <p>The default configuration store is a clone of the {@link | ||
* Configuration#getGlobalConfiguration() global configuration store}, use {@link | ||
* Configuration#NONE} to bypass using configuration settings during construction. | ||
* | ||
* @param configuration The configuration store used to | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
*/ | ||
public AzureMonitorExporterBuilder configuration(Configuration configuration) { | ||
restServiceClientBuilder.configuration(configuration); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the client options such as application ID and custom headers to set on a request. | ||
* | ||
* @param clientOptions The client options. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
*/ | ||
public AzureMonitorExporterBuilder clientOptions(ClientOptions clientOptions) { | ||
restServiceClientBuilder.clientOptions(clientOptions); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the connection string to use for exporting telemetry events to Azure Monitor. | ||
* | ||
* @param connectionString The connection string for the Azure Monitor resource. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
* @throws NullPointerException If the connection string is {@code null}. | ||
* @throws IllegalArgumentException If the connection string is invalid. | ||
*/ | ||
public AzureMonitorExporterBuilder connectionString(String connectionString) { | ||
Map<String, String> keyValues = extractKeyValuesFromConnectionString(connectionString); | ||
if (!keyValues.containsKey("InstrumentationKey")) { | ||
throw logger.logExceptionAsError( | ||
new IllegalArgumentException("InstrumentationKey not found in connectionString")); | ||
} | ||
this.instrumentationKey = keyValues.get("InstrumentationKey"); | ||
String endpoint = keyValues.get("IngestionEndpoint"); | ||
if (endpoint != null) { | ||
this.endpoint(endpoint); | ||
} | ||
this.connectionString = connectionString; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the Azure Monitor service version. | ||
* | ||
* @param serviceVersion The Azure Monitor service version. | ||
* @return The update {@link AzureMonitorExporterBuilder} object. | ||
*/ | ||
public AzureMonitorExporterBuilder serviceVersion( | ||
AzureMonitorExporterServiceVersion serviceVersion) { | ||
this.serviceVersion = serviceVersion; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the token credential required for authentication with the ingestion endpoint service. | ||
* | ||
* @param credential The Azure Identity TokenCredential. | ||
* @return The updated {@link AzureMonitorExporterBuilder} object. | ||
*/ | ||
public AzureMonitorExporterBuilder credential(TokenCredential credential) { | ||
this.credential = credential; | ||
return this; | ||
} | ||
|
||
private static Map<String, String> extractKeyValuesFromConnectionString(String connectionString) { | ||
Objects.requireNonNull(connectionString); | ||
Map<String, String> keyValues = new HashMap<>(); | ||
String[] splits = connectionString.split(";"); | ||
for (String split : splits) { | ||
String[] keyValPair = split.split("="); | ||
if (keyValPair.length == 2) { | ||
keyValues.put(keyValPair[0], keyValPair[1]); | ||
} | ||
} | ||
return keyValues; | ||
} | ||
|
||
/** | ||
* Creates a {@link MonitorExporterClient} based on options set in the builder. Every time {@code | ||
* buildAsyncClient()} is called a new instance of {@link MonitorExporterClient} is created. | ||
* | ||
* <p>If {@link #pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and {@link | ||
* #endpoint(String) endpoint} are used to create the {@link MonitorExporterAsyncClient client}. | ||
* All other builder settings are ignored. | ||
* | ||
* @return A {@link MonitorExporterClient} with the options set from the builder. | ||
* @throws NullPointerException if {@link #endpoint(String) endpoint} has not been set. | ||
*/ | ||
MonitorExporterClient buildClient() { | ||
return new MonitorExporterClient(buildAsyncClient()); | ||
} | ||
|
||
/** | ||
* Creates a {@link MonitorExporterAsyncClient} based on options set in the builder. Every time | ||
* {@code buildAsyncClient()} is called a new instance of {@link MonitorExporterAsyncClient} is | ||
* created. | ||
* | ||
* <p>If {@link #pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and {@link | ||
* #endpoint(String) endpoint} are used to create the {@link MonitorExporterAsyncClient client}. | ||
* All other builder settings are ignored. | ||
* | ||
* @return A {@link MonitorExporterAsyncClient} with the options set from the builder. | ||
*/ | ||
MonitorExporterAsyncClient buildAsyncClient() { | ||
restServiceClientBuilder.serializerAdapter(SERIALIZER_ADAPTER); | ||
if (this.credential != null) { | ||
// Add authentication policy to HttpPipeline | ||
BearerTokenAuthenticationPolicy authenticationPolicy = | ||
new BearerTokenAuthenticationPolicy( | ||
this.credential, APPLICATIONINSIGHTS_AUTHENTICATION_SCOPE); | ||
restServiceClientBuilder.addPolicy(authenticationPolicy); | ||
} | ||
ApplicationInsightsClientImpl restServiceClient = restServiceClientBuilder.buildClient(); | ||
|
||
return new MonitorExporterAsyncClient(restServiceClient); | ||
} | ||
|
||
/** | ||
* Creates an {@link AzureMonitorTraceExporter} based on the options set in the builder. This | ||
* exporter is an implementation of OpenTelemetry {@link SpanExporter}. | ||
* | ||
* @return An instance of {@link AzureMonitorTraceExporter}. | ||
* @throws NullPointerException if the connection string is not set on this builder or if the | ||
* environment variable "APPLICATIONINSIGHTS_CONNECTION_STRING" is not set. | ||
*/ | ||
public AzureMonitorTraceExporter buildTraceExporter() { | ||
if (this.connectionString == null) { | ||
// if connection string is not set, try loading from configuration | ||
Configuration configuration = Configuration.getGlobalConfiguration().clone(); | ||
connectionString(configuration.get(APPLICATIONINSIGHTS_CONNECTION_STRING)); | ||
} | ||
|
||
// instrumentationKey is extracted from connectionString, so, if instrumentationKey is null | ||
// then the error message should read "connectionString cannot be null". | ||
Objects.requireNonNull(instrumentationKey, "'connectionString' cannot be null"); | ||
return new AzureMonitorTraceExporter(buildAsyncClient(), instrumentationKey); | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
...ain/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExporterServiceVersion.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* ApplicationInsights-Java | ||
* Copyright (c) Microsoft Corporation | ||
* All rights reserved. | ||
* | ||
* MIT License | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this | ||
* software and associated documentation files (the ""Software""), to deal in the Software | ||
* without restriction, including without limitation the rights to use, copy, modify, merge, | ||
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit | ||
* persons to whom the Software is furnished to do so, subject to the following conditions: | ||
* The above copyright notice and this permission notice shall be included in all copies or | ||
* substantial portions of the Software. | ||
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE | ||
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
* DEALINGS IN THE SOFTWARE. | ||
*/ | ||
|
||
package com.azure.monitor.opentelemetry.exporter; | ||
|
||
import com.azure.core.util.ServiceVersion; | ||
|
||
/** The versions of Azure Monitor service supported by this client library. */ | ||
public enum AzureMonitorExporterServiceVersion implements ServiceVersion { | ||
/** Service version {@code 2020-09-15_Preview}. */ | ||
V2020_09_15_PREVIEW("2020-09-15_Preview"); | ||
|
||
private final String version; | ||
|
||
AzureMonitorExporterServiceVersion(String version) { | ||
this.version = version; | ||
} | ||
|
||
@Override | ||
public String getVersion() { | ||
return version; | ||
} | ||
|
||
/** | ||
* Gets the latest service version supported by this client library. | ||
* | ||
* @return the latest service version. | ||
*/ | ||
public static AzureMonitorExporterServiceVersion getLatest() { | ||
return V2020_09_15_PREVIEW; | ||
} | ||
} |
Oops, something went wrong.