Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to upload the heap dump to S3 bucket #810

Merged
merged 1 commit into from Feb 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions javamelody-collector-server/pom.xml
Expand Up @@ -79,6 +79,11 @@
<artifactId>aws-java-sdk-cloudwatch</artifactId>
<version>1.11.136</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.136</version>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
1 change: 1 addition & 0 deletions javamelody-core/build.xml
Expand Up @@ -52,6 +52,7 @@
<include name="bson-3.3.0.jar" />
<include name="aws-java-sdk-cloudwatch-1.11.136.jar" />
<include name="aws-java-sdk-core-1.11.136.jar" />
<include name="aws-java-sdk-s3-1.11.136.jar" />
<include name="javax.faces-api-2.1.jar" />
<include name="javax.el-api-2.2.1.jar" />
<include name="tomcat-jdbc-7.0.27.jar" />
Expand Down
11 changes: 11 additions & 0 deletions javamelody-core/pom.xml
Expand Up @@ -234,6 +234,17 @@
<version>1.11.136</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-core</artifactId>
<version>1.11.136</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.136</version>
</dependency>
<!-- Dépendance JUnit -->
<dependency>
<groupId>junit</groupId>
Expand Down
@@ -0,0 +1,40 @@
package net.bull.javamelody.internal.aws.s3;

import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;

/**
* Client Factory for AWS S3.
* @author Salah Qasem
*
*/

public class S3ClientFactory {

private static final String REGION = "region";

public final static S3ClientFactory INSTANCE = new S3ClientFactory();

private S3ClientFactory() {
}

/**
* Creates an AWS s3 client.
* @return AmazonS3 client
*/
public AmazonS3 createClient() {
AmazonS3ClientBuilder clientBuilder = AmazonS3Client.builder();
clientBuilder.withCredentials(new DefaultAWSCredentialsProviderChain());

if (System.getProperty(REGION) != null && !"".equals(System.getProperty(REGION).trim())) {
clientBuilder.withRegion(System.getProperty(REGION));
} else {
clientBuilder.withRegion(Regions.DEFAULT_REGION);
}
return clientBuilder.build();
}

}
@@ -0,0 +1,90 @@
package net.bull.javamelody.internal.aws.s3.util;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.AbortMultipartUploadRequest;
import com.amazonaws.services.s3.model.CompleteMultipartUploadRequest;
import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest;
import com.amazonaws.services.s3.model.InitiateMultipartUploadResult;
import com.amazonaws.services.s3.model.PartETag;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.transfer.internal.UploadPartRequestFactory;

import net.bull.javamelody.internal.aws.s3.S3ClientFactory;
import net.bull.javamelody.internal.common.LOG;
import net.bull.javamelody.internal.util.MemoryUtil;

/**
* Util class for AWS S3.
* @author Salah Qasem
*
*/
public class S3Util {

private static final long PART_SIZE = 200 * 1024 * 1024; // 200 mb

private S3Util() {

}

/**
* upload file to AWS S3.
* @param file
* @throws Exception
*/
public static void upload(File file) throws Exception {

String bucketName = System.getProperty("s3.bucketName");

if (bucketName == null || "".equals(bucketName.trim())) {
throw new IllegalStateException("s3 bucketName property can't be empty.");
}

if (getFileSizeInGiga(file) > 0.3) {
uploadMultiPart(file, bucketName);
return;
}
try {
AmazonS3 s3Client = S3ClientFactory.INSTANCE.createClient();
s3Client.putObject(bucketName, file.getName(), file);
LOG.info("File " + file.getName() + " uploaded successfully to S3");
} catch (Exception e) {
throw e;
}
}

private static void uploadMultiPart(File file, String bucketName) throws Exception {
AmazonS3 s3Client = S3ClientFactory.INSTANCE.createClient();
List<PartETag> partETags = new ArrayList<PartETag>();

InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName,
file.getName());
InitiateMultipartUploadResult initResponse = s3Client.initiateMultipartUpload(initRequest);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, file.getName(), file);
UploadPartRequestFactory requestFactory = new UploadPartRequestFactory(putObjectRequest,
initResponse.getUploadId(), PART_SIZE);

try {
while (requestFactory.hasMoreRequests()) {
partETags.add(s3Client.uploadPart(requestFactory.getNextUploadPartRequest())
.getPartETag());
}
CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(
bucketName, file.getName(), initResponse.getUploadId(), partETags);
s3Client.completeMultipartUpload(compRequest);
LOG.info("File " + file.getName() + " uploaded successfully to S3");
} catch (Exception e) {
s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(bucketName,
file.getName(), initResponse.getUploadId()));
throw e;
}

}

private static double getFileSizeInGiga(File file) {
return (file.length() * 1.0) / MemoryUtil.Size.GIGA_BYTE.getByteSize();
}
}
Expand Up @@ -37,6 +37,7 @@

import net.bull.javamelody.Parameter;
import net.bull.javamelody.SessionListener;
import net.bull.javamelody.internal.aws.s3.util.S3Util;
import net.bull.javamelody.internal.common.I18N;
import net.bull.javamelody.internal.common.InputOutput;
import net.bull.javamelody.internal.common.LOG;
Expand Down Expand Up @@ -212,14 +213,24 @@ public String execute(Collector collector, CollectorServer collectorServer, // N
// heap dump à générer dans le répertoire temporaire sur le serveur
// avec un suffixe contenant le host, la date et l'heure et avec une extension hprof
// (utiliser jvisualvm du jdk ou MAT d'eclipse en standalone ou en plugin)
String message = "";
final File heapDump = heapDump();
final File zipFile = new File(heapDump.getParentFile(),
heapDump.getName() + ".zip");
InputOutput.zipFile(heapDump, zipFile);
InputOutput.deleteFile(heapDump);
final String path = zipFile.getPath();
messageForReport = I18N.getFormattedString("heap_dump_genere",
path.replace('\\', '/'));
if (Boolean.valueOf(System.getProperty("enable.s3.heapDump"))) {
try {
S3Util.upload(zipFile);
message = "heap dump " + zipFile.getName()
+ " uploaded successfully to s3.";
} catch (Exception e) {
message = "Failed to upload heap to s3 - " + e.getMessage() + "\n";
}
}
messageForReport = message
+ I18N.getFormattedString("heap_dump_genere", path.replace('\\', '/'));
}
break;
case INVALIDATE_SESSIONS:
Expand Down
@@ -0,0 +1,34 @@
package net.bull.javamelody.internal.util;

public class MemoryUtil {

public enum Size {
KILO_BYTE(1024L),
MEGA_BYTE(KILO_BYTE.byteSize * 1024L),
GIGA_BYTE(MEGA_BYTE.byteSize * 1024L);

private long byteSize;

Size(long byteSize) {
this.byteSize = byteSize;
}

public long getByteSize() {
return byteSize;
}
}

private MemoryUtil() {

}

/**
* Gets the used memory measured by Kilobyte, MB, or GB based in the size param.
* @param size
* @return double represent the total JVM used memory.
*/
public static double getUsedMemory(MemoryUtil.Size size) {
return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
/ (size.byteSize * 1.0);
}
}
Binary file not shown.
5 changes: 5 additions & 0 deletions javamelody-swing/pom.xml
Expand Up @@ -108,6 +108,11 @@
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.136</version>
</dependency>
</dependencies>

<distributionManagement>
Expand Down
5 changes: 5 additions & 0 deletions javamelody-test-webapp/pom.xml
Expand Up @@ -229,6 +229,11 @@
<version>1.11.136</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.136</version>
</dependency>
<!-- Dépendance JUnit -->
<dependency>
<groupId>junit</groupId>
Expand Down