Skip to content

Commit e68cbfa

Browse files
authored
Merge branch 'google:main' into main
2 parents e5c9d64 + 2dee75a commit e68cbfa

File tree

47 files changed

+3093
-398
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+3093
-398
lines changed

dumper/app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ dependencies {
128128
implementation libs.logback.classic
129129
implementation libs.jcl.over.slf4j
130130

131+
implementation libs.async.profiler
132+
131133
runtimeOnly libs.postgresql
132134
runtimeOnly libs.snowflake.jdbc
133135
runtimeOnly libs.redshift.jdbc

dumper/app/gradle.lockfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
ch.qos.logback:logback-classic:1.3.16=compileClasspath,runtimeClasspath,sources,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
55
ch.qos.logback:logback-core:1.3.16=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
66
com.amazon.redshift:redshift-jdbc42:2.1.0.32=runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
7+
tools.profiler:async-profiler:4.2=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
78
com.amazonaws:aws-java-sdk-cloudwatch:1.12.791=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
89
com.amazonaws:aws-java-sdk-core:1.12.791=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
910
com.amazonaws:aws-java-sdk-redshift:1.12.791=compileClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/Main.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@
2020

2121
import com.google.common.base.Throwables;
2222
import com.google.common.collect.ImmutableList;
23+
import java.io.File;
24+
import java.io.IOException;
25+
import java.net.URI;
26+
import java.nio.file.*;
27+
import java.util.Collections;
28+
import java.util.Map;
2329
import java.util.Objects;
30+
import one.profiler.AsyncProfiler;
2431
import org.slf4j.Logger;
2532
import org.slf4j.LoggerFactory;
2633

@@ -51,13 +58,21 @@ private static void printErrorMessages(Throwable e) {
5158

5259
public static void main(String... args) throws Exception {
5360
try {
61+
AsyncProfiler asyncProfiler = AsyncProfiler.getInstance();
62+
asyncProfiler.execute("start,event=cpu,interval=10ms");
63+
5464
StartUpMetaInfoProcessor.printMetaInfo();
5565

5666
if (args.length == 0) {
5767
args = new String[] {"--help"};
5868
}
5969

60-
MetadataDumper metadataDumper = new MetadataDumper(args);
70+
MetadataDumper metadataDumper =
71+
new MetadataDumper(
72+
(outputFileLocation) -> {
73+
stopProfileAndAppendToZip(asyncProfiler, outputFileLocation);
74+
},
75+
args);
6176

6277
if (!metadataDumper.run()) {
6378
System.exit(1);
@@ -74,4 +89,29 @@ public static void main(String... args) throws Exception {
7489
System.exit(1);
7590
}
7691
}
92+
93+
private static void stopProfileAndAppendToZip(
94+
AsyncProfiler asyncProfiler, String outputFileLocation) {
95+
try {
96+
File tempFlameGraph = File.createTempFile("flamegraph", ".html");
97+
String stopCommand = "stop,output=flamegraph,file=" + tempFlameGraph.getAbsolutePath();
98+
asyncProfiler.execute(stopCommand);
99+
100+
moveFileToZip(outputFileLocation, tempFlameGraph, "flamegraph.html");
101+
} catch (Exception ignored) {
102+
}
103+
}
104+
105+
private static void moveFileToZip(String zipFile, File file, String entryName)
106+
throws IOException {
107+
Map<String, String> env = Collections.singletonMap("create", "false");
108+
URI zipUri = URI.create("jar:" + Paths.get(zipFile).toUri());
109+
110+
try (FileSystem zipFs = FileSystems.newFileSystem(zipUri, env)) {
111+
Path pathInZip = zipFs.getPath(entryName);
112+
113+
Files.copy(file.toPath(), pathInZip, StandardCopyOption.REPLACE_EXISTING);
114+
Files.deleteIfExists(file.toPath());
115+
}
116+
}
77117
}

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/MetadataDumper.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,24 @@ public class MetadataDumper {
6161
private static final Pattern GCS_PATH_PATTERN =
6262
Pattern.compile("gs://(?<bucket>[^/]+)/(?<path>.*)");
6363

64-
private TelemetryProcessor telemetryProcessor;
65-
private ConnectorArguments connectorArguments;
64+
private final TelemetryProcessor telemetryProcessor;
65+
private final ConnectorArguments connectorArguments;
66+
private final ShutdownHook shutdownHook;
6667

6768
public MetadataDumper(String... args) throws Exception {
69+
this((zipPath) -> {}, args);
70+
}
71+
72+
public MetadataDumper(ShutdownHook shutdownHook, String... args) throws Exception {
6873
this.connectorArguments = new ConnectorArguments(JsonResponseFile.addResponseFiles(args));
6974
telemetryProcessor =
7075
new TelemetryProcessor(
7176
TelemetryStrategyFactory.createStrategy(connectorArguments.isTelemetryOn()));
7277
if (connectorArguments.saveResponseFile()) {
7378
JsonResponseFile.save(connectorArguments);
7479
}
80+
81+
this.shutdownHook = shutdownHook;
7582
}
7683

7784
public boolean run() throws Exception {
@@ -158,6 +165,8 @@ protected boolean run(@Nonnull Connector connector) throws Exception {
158165
connectorArguments, state, stopwatch, requiredTaskSucceeded);
159166
telemetryProcessor.processTelemetry(fileSystem);
160167
} finally {
168+
shutdownHook.shutdown(outputFileLocation);
169+
161170
// We must do this in finally after the ZipFileSystem has been closed.
162171
File outputFile = new File(outputFileLocation);
163172
if (outputFile.isFile()) {
@@ -301,4 +310,9 @@ private void logFinalSummary(
301310
linePrinter.println("Dumper execution: " + stateToPrint);
302311
});
303312
}
313+
314+
@FunctionalInterface
315+
public interface ShutdownHook {
316+
void shutdown(String outputzip);
317+
}
304318
}

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/cloudera/manager/AbstractClouderaTimeSeriesTask.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.fasterxml.jackson.databind.JsonNode;
2020
import com.google.common.base.Preconditions;
21+
import com.google.edwmigration.dumper.application.dumper.task.TaskCategory;
2122
import java.net.URI;
2223
import java.time.ZonedDateTime;
2324
import java.time.format.DateTimeFormatter;
@@ -33,12 +34,14 @@ abstract class AbstractClouderaTimeSeriesTask extends AbstractClouderaManagerTas
3334
private final ZonedDateTime startDate;
3435
private final ZonedDateTime endDate;
3536
private final TimeSeriesAggregation tsAggregation;
37+
private final TaskCategory taskCategory;
3638

3739
public AbstractClouderaTimeSeriesTask(
3840
@Nonnull String targetPath,
3941
@Nonnull ZonedDateTime startDate,
4042
@Nonnull ZonedDateTime endDate,
41-
@Nonnull TimeSeriesAggregation tsAggregation) {
43+
@Nonnull TimeSeriesAggregation tsAggregation,
44+
@Nonnull TaskCategory taskCategory) {
4245
super(targetPath);
4346
Preconditions.checkNotNull(targetPath, "Target path must be not null.");
4447
Preconditions.checkState(!targetPath.isEmpty(), "Target file path must be not empty.");
@@ -50,6 +53,13 @@ public AbstractClouderaTimeSeriesTask(
5053
this.startDate = startDate;
5154
this.endDate = endDate;
5255
this.tsAggregation = tsAggregation;
56+
this.taskCategory = taskCategory;
57+
}
58+
59+
@Nonnull
60+
@Override
61+
public TaskCategory getCategory() {
62+
return taskCategory;
5363
}
5464

5565
protected JsonNode requestTimeSeriesChart(ClouderaManagerHandle handle, String query)

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/cloudera/manager/ClouderaAPIHostsTask.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ protected void doRun(
8080
hosts.add(ClouderaHostDTO.create(apiHost.getId(), apiHost.getName()));
8181
}
8282
}
83-
handle.initHostsIfNull(hosts);
83+
if (hosts.isEmpty()) {
84+
throw new MetadataDumperUsageException(
85+
"No hosts were found in any of the initialized Cloudera clusters.");
86+
}
87+
handle.initHosts(hosts);
8488
}
8589
}
8690
}

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/cloudera/manager/ClouderaCMFHostsTask.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,11 @@
2020
import com.fasterxml.jackson.databind.JsonNode;
2121
import com.google.common.io.ByteSink;
2222
import com.google.edwmigration.dumper.application.dumper.connector.cloudera.manager.ClouderaManagerHandle.ClouderaClusterDTO;
23-
import com.google.edwmigration.dumper.application.dumper.connector.cloudera.manager.ClouderaManagerHandle.ClouderaHostDTO;
24-
import com.google.edwmigration.dumper.application.dumper.connector.cloudera.manager.dto.CMFHostDTO;
25-
import com.google.edwmigration.dumper.application.dumper.connector.cloudera.manager.dto.CMFHostListDTO;
2623
import com.google.edwmigration.dumper.application.dumper.task.TaskCategory;
2724
import com.google.edwmigration.dumper.application.dumper.task.TaskRunContext;
2825
import java.io.Writer;
2926
import java.net.URI;
3027
import java.nio.charset.StandardCharsets;
31-
import java.util.ArrayList;
3228
import java.util.List;
3329
import javax.annotation.Nonnull;
3430
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -67,7 +63,6 @@ protected void doRun(
6763
}
6864

6965
final URI baseURI = handle.getBaseURI();
70-
List<ClouderaHostDTO> hosts = new ArrayList<>();
7166
try (Writer writer = sink.asCharSink(StandardCharsets.UTF_8).openBufferedStream()) {
7267
for (ClouderaClusterDTO cluster : clusters) {
7368
if (cluster.getId() == null) {
@@ -95,14 +90,7 @@ protected void doRun(
9590
String stringifiedHosts = hostsJson.toString();
9691
writer.write(stringifiedHosts);
9792
writer.write('\n');
98-
99-
CMFHostListDTO apiHosts = parseJsonStringToObject(stringifiedHosts, CMFHostListDTO.class);
100-
for (CMFHostDTO apiHost : apiHosts.getHosts()) {
101-
hosts.add(ClouderaHostDTO.create(apiHost.getId(), apiHost.getName()));
102-
}
10393
}
10494
}
105-
106-
handle.initHostsIfNull(hosts);
10795
}
10896
}

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/cloudera/manager/ClouderaClusterCPUChartTask.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.common.io.ByteSink;
2121
import com.google.edwmigration.dumper.application.dumper.MetadataDumperUsageException;
2222
import com.google.edwmigration.dumper.application.dumper.connector.cloudera.manager.ClouderaManagerHandle.ClouderaClusterDTO;
23+
import com.google.edwmigration.dumper.application.dumper.task.TaskCategory;
2324
import com.google.edwmigration.dumper.application.dumper.task.TaskRunContext;
2425
import java.io.Writer;
2526
import java.nio.charset.StandardCharsets;
@@ -40,13 +41,16 @@
4041
* language.
4142
*/
4243
public class ClouderaClusterCPUChartTask extends AbstractClouderaTimeSeriesTask {
43-
private static final Logger logger = LoggerFactory.getLogger(ClouderaCMFHostsTask.class);
44+
private static final Logger logger = LoggerFactory.getLogger(ClouderaClusterCPUChartTask.class);
4445
private static final String TS_CPU_QUERY_TEMPLATE =
4546
"SELECT cpu_percent_across_hosts WHERE entityName = \"%s\" AND category = CLUSTER";
4647

4748
public ClouderaClusterCPUChartTask(
48-
ZonedDateTime startDate, ZonedDateTime endDate, TimeSeriesAggregation tsAggregation) {
49-
super("cluster-cpu.jsonl", startDate, endDate, tsAggregation);
49+
ZonedDateTime startDate,
50+
ZonedDateTime endDate,
51+
TimeSeriesAggregation tsAggregation,
52+
TaskCategory taskCategory) {
53+
super("cluster-cpu.jsonl", startDate, endDate, tsAggregation, taskCategory);
5054
}
5155

5256
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2022-2025 Google LLC
3+
* Copyright 2013-2021 CompilerWorks
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.google.edwmigration.dumper.application.dumper.connector.cloudera.manager;
18+
19+
import com.google.edwmigration.dumper.application.dumper.ConnectorArguments;
20+
import java.io.IOException;
21+
import javax.annotation.Nonnull;
22+
import org.apache.http.client.methods.CloseableHttpResponse;
23+
import org.apache.http.client.methods.HttpGet;
24+
import org.apache.http.util.EntityUtils;
25+
26+
/** Utility class for verifying the preconditions and configuration of a Cloudera Connector. */
27+
public final class ClouderaConnectorVerifier {
28+
29+
private ClouderaConnectorVerifier() {}
30+
31+
/**
32+
* Verifies the validity of the connector configuration and environment.
33+
*
34+
* <p>This involves checking connectivity to the API, verifying the existence of the specified
35+
* cluster (if provided), and ensuring other preconditions are met.
36+
*
37+
* @param handle The handle to the Cloudera Manager API.
38+
* @param arguments The connector arguments containing target cluster details.
39+
* @throws ClouderaConnectorException If verification fails due to missing resources, API errors,
40+
* or connectivity issues.
41+
*/
42+
public static void verify(
43+
@Nonnull ClouderaManagerHandle handle, @Nonnull ConnectorArguments arguments)
44+
throws ClouderaConnectorException {
45+
verifyClusterExists(handle, arguments.getCluster());
46+
}
47+
48+
private static void verifyClusterExists(ClouderaManagerHandle handle, String clusterName)
49+
throws ClouderaConnectorException {
50+
if (clusterName == null) {
51+
return;
52+
}
53+
String endpoint = String.format("%s/clusters/%s", handle.getApiURI(), clusterName);
54+
HttpGet httpGet = new HttpGet(endpoint);
55+
56+
try (CloseableHttpResponse response = handle.getHttpClient().execute(httpGet)) {
57+
58+
int statusCode = response.getStatusLine().getStatusCode();
59+
60+
if (statusCode == 404) {
61+
throw new ClouderaConnectorException(
62+
String.format("Specified cluster '%s' not found.", clusterName));
63+
}
64+
65+
if (!isHttpStatusSuccess(statusCode)) {
66+
String errorMsg = EntityUtils.toString(response.getEntity());
67+
throw new ClouderaConnectorException(
68+
String.format(
69+
"Unexpected API error checking cluster '%s'. Code: %d. Message: %s",
70+
clusterName, statusCode, errorMsg));
71+
}
72+
} catch (IOException e) {
73+
throw new ClouderaConnectorException(
74+
String.format(
75+
"Failed to communicate with Cloudera Manager API while checking cluster '%s'.",
76+
clusterName),
77+
e);
78+
}
79+
}
80+
81+
private static boolean isHttpStatusSuccess(int statusCode) {
82+
return statusCode >= 200 && statusCode < 300;
83+
}
84+
}

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/cloudera/manager/ClouderaHostRAMChartTask.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.common.io.ByteSink;
2121
import com.google.edwmigration.dumper.application.dumper.MetadataDumperUsageException;
2222
import com.google.edwmigration.dumper.application.dumper.connector.cloudera.manager.ClouderaManagerHandle.ClouderaHostDTO;
23+
import com.google.edwmigration.dumper.application.dumper.task.TaskCategory;
2324
import com.google.edwmigration.dumper.application.dumper.task.TaskRunContext;
2425
import java.io.Writer;
2526
import java.nio.charset.StandardCharsets;
@@ -40,14 +41,17 @@
4041
*/
4142
public class ClouderaHostRAMChartTask extends AbstractClouderaTimeSeriesTask {
4243

43-
private static final Logger logger = LoggerFactory.getLogger(ClouderaCMFHostsTask.class);
44+
private static final Logger logger = LoggerFactory.getLogger(ClouderaHostRAMChartTask.class);
4445

4546
private static final String TS_RAM_QUERY_TEMPLATE =
4647
"select swap_used, physical_memory_used, physical_memory_total, physical_memory_cached, physical_memory_buffers where entityName = \"%s\"";
4748

4849
public ClouderaHostRAMChartTask(
49-
ZonedDateTime startDate, ZonedDateTime endDate, TimeSeriesAggregation tsAggregation) {
50-
super("host-ram.jsonl", startDate, endDate, tsAggregation);
50+
ZonedDateTime startDate,
51+
ZonedDateTime endDate,
52+
TimeSeriesAggregation tsAggregation,
53+
TaskCategory taskCategory) {
54+
super("host-ram.jsonl", startDate, endDate, tsAggregation, taskCategory);
5155
}
5256

5357
@Override

0 commit comments

Comments
 (0)