Skip to content

Commit

Permalink
[Monitor] Enabling Sovereign Cloud Support for Monitor Query (#36063)
Browse files Browse the repository at this point in the history
* README.md adjustments

* Adding Sovereign Cloud Support

* Adding Sovereign Cloud Support
- fixing linting errors

* Update tests.yml

* Update tests.yml

* Adding Sovereign Cloud Support

* Adding Sovereign Cloud Support

* Adding Sovereign Cloud Support

* Adding Sovereign Cloud Support

* Adding Sovereign Cloud Support

* Adding Sovereign Cloud Support

* Update LogsQueryAsyncClientTest.java

* Update LogsQueryAsyncClientTest.java

* Update LogsQueryClientTest.java

* Enable Testing in Sovereign Clouds and build failure fixes

* Add cspell exception for test-resources.json

* Addressing failing CI

* Changes to enable testing in sovereign clouds

* Addressing failing CI

* Addressing failing CI

* Addressing failing CI

* Refactoring test static variables and updating test-resources.json

* Test Edits

* Test Edits

* Test Edits

* Tests.yml Edits

* Add china testing and documentation

* Updating tests and test resources

* Updating CHANGELOG.md

* Updating README.md

* Revert README.md

* Updating README.md

* Update sdk/monitor/azure-monitor-query/README.md

Co-authored-by: Srikanta <[email protected]>

* Updating MonitorQueryTestUtils.java

* Updating MonitorQueryTestUtils.java

---------

Co-authored-by: Srikanta <[email protected]>
  • Loading branch information
jairmyree and srnagar authored Jul 27, 2023
1 parent 3db496d commit f628424
Show file tree
Hide file tree
Showing 16 changed files with 329 additions and 122 deletions.
1 change: 1 addition & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
"sdk/maps/azure-maps-search/**",
"sdk/monitor/azure-monitor-query/**",
"sdk/monitor/azure-monitor-opentelemetry-exporter/**",
"sdk/monitor/test-resources.json",
"sdk/modelsrepository/azure-iot-modelsrepository/**",
"sdk/parents/azure-client-sdk-parent/**",
"sdk/parents/azure-sdk-parent/**",
Expand Down
2 changes: 2 additions & 0 deletions sdk/monitor/azure-monitor-query/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### Bugs Fixed

- Fixed bug that disabled sovereign cloud support.

### Other Changes

## 1.2.2 (2023-07-25)
Expand Down
24 changes: 24 additions & 0 deletions sdk/monitor/azure-monitor-query/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,28 @@ MetricsQueryAsyncClient metricsQueryAsyncClient = new MetricsQueryClientBuilder(
.buildAsyncClient();
```

#### Configure clients for non-public Azure clouds

By default, `LogQueryClient` and `MetricQueryClient` are configured to connect to the public Azure Cloud. These can be configured to connect to non-public Azure clouds by setting the correct `endpoint` in the client builders: For example:

Creating a `LogsQueryClient` for Azure China cloud:

```java readme-sample-createLogsQueryClientWithSovereignCloud
LogsQueryClient logsQueryClient = new LogsQueryClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
.endpoint("https://api.loganalytics.azure.cn/v1")
.buildClient();
```

Creating a `MetricsQueryClient` for Azure China cloud:

```java readme-sample-createMetricsQueryClientWithSovereignCloud
MetricsQueryClient metricsQueryClient = new MetricsQueryClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
.endpoint("https://management.chinacloudapi.cn")
.buildClient();
```

### Execute the query

For examples of Logs and Metrics queries, see the [Examples](#examples) section.
Expand Down Expand Up @@ -149,6 +171,7 @@ Each set of metric values is a time series with the following characteristics:
- [Map logs query results to a model](#map-logs-query-results-to-a-model)
- [Handle logs query response](#handle-logs-query-response)
- [Query logs by resource id](#query-logs-by-resource-id)
- [Create a log client for non-public Azure clouds](#configure-clients-for-non-public-azure-clouds)
- [Batch logs query](#batch-logs-query)
- [Advanced logs query scenarios](#advanced-logs-query-scenarios)
- [Set logs query timeout](#set-logs-query-timeout)
Expand All @@ -158,6 +181,7 @@ Each set of metric values is a time series with the following characteristics:
- [Metrics query](#metrics-query)
- [Handle metrics query response](#handle-metrics-query-response)
- [Get average and count metrics](#get-average-and-count-metrics)
- [Create a metrics client for non-public Azure clouds](#configure-clients-for-non-public-azure-clouds)

### Logs query

Expand Down
2 changes: 1 addition & 1 deletion sdk/monitor/azure-monitor-query/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/monitor/azure-monitor-query",
"Tag": "java/monitor/azure-monitor-query_a5e00f5064"
"Tag": "java/monitor/azure-monitor-query_9cf6f47b0a"
}
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ private Response<LogsQueryResult> queryResourceWithResponseInternal(String resou
Objects.requireNonNull(resourceId, "'resourceId' cannot be null.");
Objects.requireNonNull(query, "'query' cannot be null.");

if (resourceId.startsWith("/")) {
resourceId = resourceId.substring(1);
}

String preferHeader = buildPreferHeaderString(options);
context = updateContext(options.getServerTimeout(), context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,19 @@ private HttpPipeline createHttpPipeline() {
policies.add(new AddDatePolicy());
policies.add(new CookiePolicy());
if (tokenCredential != null) {
String localHost = (host != null) ? host : "https://api.loganalytics.io";
policies.add(new BearerTokenAuthenticationPolicy(tokenCredential, String.format("%s/.default", localHost)));
String localHost;
if (host != null) {
try {
localHost = new java.net.URL(host).getHost();
} catch (java.net.MalformedURLException e) {
throw new RuntimeException(e);
}
} else {
localHost = "api.loganalytics.io";
}
policies.add(
new BearerTokenAuthenticationPolicy(
tokenCredential, String.format("https://%s/.default", localHost)));
}
this.pipelinePolicies.stream()
.filter(p -> p.getPipelinePosition() == HttpPipelinePosition.PER_RETRY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,4 +399,28 @@ public void includeVisualization() throws IOException {
System.out.println("Visualization graph type = " + visualizationJson.get("visualization").asText());
// END: readme-sample-includevisualization
}

/**
* Sample to show how to create a log query client using a sovereign cloud endpoint.
*/
public void createLogsClientWithSovereignCloud() {
// BEGIN: readme-sample-createLogsQueryClientWithSovereignCloud
LogsQueryClient logsQueryClient = new LogsQueryClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
.endpoint("https://api.loganalytics.azure.cn/v1")
.buildClient();
// END: readme-sample-createLogsQueryClientWithSovereignCloud
}

/**
* Sample to show how to create a metrics query client using a sovereign cloud endpoint.
*/
public void createMetricsClientWithSovereignCloud() {
// BEGIN: readme-sample-createMetricsQueryClientWithSovereignCloud
MetricsQueryClient metricsQueryClient = new MetricsQueryClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
.endpoint("https://management.chinacloudapi.cn")
.buildClient();
// END: readme-sample-createMetricsQueryClientWithSovereignCloud
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.azure.core.test.TestMode;
import com.azure.core.test.TestProxyTestBase;
import com.azure.core.test.http.AssertingHttpClientBuilder;
import com.azure.core.util.Configuration;
import com.azure.core.util.Context;
import com.azure.core.util.serializer.TypeReference;
import com.azure.identity.DefaultAzureCredentialBuilder;
Expand All @@ -37,6 +36,8 @@
import java.util.LinkedHashMap;
import java.util.List;

import static com.azure.monitor.query.MonitorQueryTestUtils.*;
import static com.azure.monitor.query.MonitorQueryTestUtils.getLogResourceId;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
Expand All @@ -47,21 +48,16 @@
*/
public class LogsQueryAsyncClientTest extends TestProxyTestBase {

private static final String WORKSPACE_ID = Configuration.getGlobalConfiguration()
.get("AZURE_MONITOR_LOGS_WORKSPACE_ID", "d2d0e126-fa1e-4b0a-b647-250cdd471e68");
private LogsQueryAsyncClient client;

static final String RESOURCE_ID = Configuration.getGlobalConfiguration()
.get("AZURE_MONITOR_LOGS_RESOURCE_ID", "subscriptions/faa080af-c1d8-40ad-9cce-e1a450ca5b57/resourceGroups/srnagar-azuresdkgroup/providers/Microsoft.Storage/storageAccounts/srnagarstorage");
private String workspaceId;

private LogsQueryAsyncClient client;
private static final String QUERY_STRING = "let dt = datatable (DateTime: datetime, Bool:bool, Guid: guid, Int: "
+ "int, Long:long, Double: double, String: string, Timespan: timespan, Decimal: decimal, Dynamic: dynamic)\n"
+ "[datetime(2015-12-31 23:59:59.9), false, guid(74be27de-1e4e-49d9-b579-fe0b331d3642), 12345, 1, 12345.6789,"
+ " 'string value', 10s, decimal(0.10101), dynamic({\"a\":123, \"b\":\"hello\", \"c\":[1,2,3], \"d\":{}})];"
+ "range x from 1 to 100 step 1 | extend y=1 | join kind=fullouter dt on $left.y == $right.Long";
private String resourceId;

@BeforeEach
public void setup() {
workspaceId = getLogWorkspaceId(interceptorManager.isPlaybackMode());
resourceId = getLogResourceId(interceptorManager.isPlaybackMode());
LogsQueryClientBuilder clientBuilder = new LogsQueryClientBuilder()
.retryPolicy(new RetryPolicy(new RetryStrategy() {
@Override
Expand All @@ -84,6 +80,7 @@ public Duration calculateRetryDelay(int i) {
.credential(getCredential());
} else if (getTestMode() == TestMode.LIVE) {
clientBuilder.credential(getCredential());
clientBuilder.endpoint(MonitorQueryTestUtils.getLogEndpoint());
}
this.client = clientBuilder
.buildAsyncClient();
Expand All @@ -102,7 +99,7 @@ private TokenCredential getCredential() {

@Test
public void testLogsQuery() {
StepVerifier.create(client.queryWorkspace(WORKSPACE_ID, QUERY_STRING,
StepVerifier.create(client.queryWorkspace(workspaceId, QUERY_STRING,
new QueryTimeInterval(OffsetDateTime.of(LocalDateTime.of(2021, 01, 01, 0, 0), ZoneOffset.UTC),
OffsetDateTime.of(LocalDateTime.of(2021, 06, 10, 0, 0), ZoneOffset.UTC))))
.assertNext(queryResults -> {
Expand All @@ -115,7 +112,7 @@ public void testLogsQuery() {

@Test
public void testLogsResourceQuery() {
StepVerifier.create(client.queryResource(RESOURCE_ID, QUERY_STRING,
StepVerifier.create(client.queryResource(resourceId, QUERY_STRING,
QueryTimeInterval.ALL))
.assertNext(queryResults -> {
assertEquals(1, queryResults.getAllTables().size());
Expand All @@ -138,7 +135,7 @@ public void testLogsQueryAllowPartialSuccess() {
final QueryTimeInterval interval = QueryTimeInterval.LAST_DAY;

// Act
StepVerifier.create(client.queryWorkspaceWithResponse(WORKSPACE_ID,
StepVerifier.create(client.queryWorkspaceWithResponse(workspaceId,
query, interval, options, Context.NONE))
.assertNext(response -> {
// Assert
Expand All @@ -155,8 +152,8 @@ public void testLogsQueryAllowPartialSuccess() {
@Test
public void testLogsQueryBatch() {
LogsBatchQuery logsBatchQuery = new LogsBatchQuery();
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING + " | take 2", null);
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING + "| take 3", null);
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING + " | take 2", null);
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING + "| take 3", null);

StepVerifier.create(client
.queryBatchWithResponse(logsBatchQuery, Context.NONE))
Expand All @@ -179,10 +176,10 @@ public void testLogsQueryBatch() {
@Test
public void testLogsQueryBatchWithServerTimeout() {
LogsBatchQuery logsBatchQuery = new LogsBatchQuery();
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING + " | take 2", null);
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING + " | take 5", null,
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING + " | take 2", null);
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING + " | take 5", null,
new LogsQueryOptions().setServerTimeout(Duration.ofSeconds(20)));
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING + "| take 3", null,
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING + "| take 3", null,
new LogsQueryOptions().setServerTimeout(Duration.ofSeconds(10)));

StepVerifier.create(client
Expand Down Expand Up @@ -211,7 +208,7 @@ public void testLogsQueryBatchWithServerTimeout() {
@DisabledIfEnvironmentVariable(named = "AZURE_TEST_MODE", matches = "LIVE", disabledReason = "multi-workspace "
+ "queries require sending logs to Azure Monitor first. So, run this test in playback or record mode only.")
public void testMultipleWorkspaces() {
StepVerifier.create(client.queryWorkspaceWithResponse(WORKSPACE_ID,
StepVerifier.create(client.queryWorkspaceWithResponse(workspaceId,
"union * | where TimeGenerated > ago(100d) | project TenantId | summarize count() by TenantId", null,
new LogsQueryOptions()
.setAdditionalWorkspaces(Arrays.asList("9dad0092-fd13-403a-b367-a189a090a541")),
Expand All @@ -233,8 +230,8 @@ public void testMultipleWorkspaces() {
@Test
public void testBatchQueryPartialSuccess() {
LogsBatchQuery logsBatchQuery = new LogsBatchQuery();
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING + " | take 2", null);
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING + " | take", null);
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING + " | take 2", null);
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING + " | take", null);

StepVerifier.create(client
.queryBatchWithResponse(logsBatchQuery, Context.NONE))
Expand All @@ -254,7 +251,7 @@ public void testBatchQueryPartialSuccess() {

@Test
public void testStatistics() {
StepVerifier.create(client.queryWorkspaceWithResponse(WORKSPACE_ID,
StepVerifier.create(client.queryWorkspaceWithResponse(workspaceId,
QUERY_STRING, null, new LogsQueryOptions().setIncludeStatistics(true), Context.NONE))
.assertNext(response -> {
LogsQueryResult queryResults = response.getValue();
Expand All @@ -266,7 +263,7 @@ QUERY_STRING, null, new LogsQueryOptions().setIncludeStatistics(true), Context.N

@Test
public void testStatisticsResourceQuery() {
StepVerifier.create(client.queryResourceWithResponse(RESOURCE_ID,
StepVerifier.create(client.queryResourceWithResponse(resourceId,
QUERY_STRING, null, new LogsQueryOptions().setIncludeStatistics(true), Context.NONE))
.assertNext(response -> {
LogsQueryResult queryResults = response.getValue();
Expand All @@ -279,9 +276,9 @@ QUERY_STRING, null, new LogsQueryOptions().setIncludeStatistics(true), Context.N
@Test
public void testBatchStatistics() {
LogsBatchQuery logsBatchQuery = new LogsBatchQuery();
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING, null);
logsBatchQuery.addWorkspaceQuery(WORKSPACE_ID, QUERY_STRING, null,
new LogsQueryOptions().setIncludeStatistics(true));
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING, null);
logsBatchQuery.addWorkspaceQuery(workspaceId, QUERY_STRING, null,
new LogsQueryOptions().setIncludeStatistics(true));

StepVerifier.create(client
.queryBatchWithResponse(logsBatchQuery, Context.NONE))
Expand Down Expand Up @@ -314,7 +311,7 @@ public void testServerTimeout() {
long count = 1000000006959L;
// this query should take more than 5 seconds usually, but the server may have cached the
// response and may return before 5 seconds. So, retry with another query (different count value)
StepVerifier.create(client.queryWorkspaceWithResponse(WORKSPACE_ID, "range x from 1 to " + count + " "
StepVerifier.create(client.queryWorkspaceWithResponse(workspaceId, "range x from 1 to " + count + " "
+ "step 1 | count",
null,
new LogsQueryOptions()
Expand All @@ -334,7 +331,7 @@ public void testServerTimeout() {
public void testVisualization() {
String query = "datatable (s: string, i: long) [ \"a\", 1, \"b\", 2, \"c\", 3 ] "
+ "| render columnchart with (title=\"the chart title\", xtitle=\"the x axis title\")";
StepVerifier.create(client.queryWorkspaceWithResponse(WORKSPACE_ID,
StepVerifier.create(client.queryWorkspaceWithResponse(workspaceId,
query, null, new LogsQueryOptions().setIncludeStatistics(true).setIncludeVisualization(true),
Context.NONE))
.assertNext(response -> {
Expand All @@ -361,7 +358,7 @@ query, null, new LogsQueryOptions().setIncludeStatistics(true).setIncludeVisuali
public void testVisualizationResourceQuery() {
String query = "datatable (s: string, i: long) [ \"a\", 1, \"b\", 2, \"c\", 3 ] "
+ "| render columnchart with (title=\"the chart title\", xtitle=\"the x axis title\")";
StepVerifier.create(client.queryResourceWithResponse(RESOURCE_ID,
StepVerifier.create(client.queryResourceWithResponse(resourceId,
query, null, new LogsQueryOptions().setIncludeStatistics(true).setIncludeVisualization(true),
Context.NONE))
.assertNext(response -> {
Expand Down
Loading

0 comments on commit f628424

Please sign in to comment.