Skip to content

Instantly share code, notes, and snippets.

@parahall
Created March 19, 2016 14:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save parahall/cbba57d9d10f6dcd850f to your computer and use it in GitHub Desktop.
Save parahall/cbba57d9d10f6dcd850f to your computer and use it in GitHub Desktop.
Sending Leak Traces to a Slack Channel using Retrofit2
import com.squareup.leakcanary.AnalysisResult;
import com.squareup.leakcanary.DisplayLeakService;
import com.squareup.leakcanary.HeapDump;
import android.util.Log;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.Query;
//Service to upload memory leaks to slack. Inspired by https://gist.github.com/pyricau/06c2c486d24f5f85f7f0
//adopted to use Retrofit2
public final class LeakSlackUploadService extends DisplayLeakService
implements Callback<LeakSlackUploadService.UploadFileResponse> {
private SlackApi slackApi;
@Override
public void onCreate() {
super.onCreate();
slackApi = new Retrofit.Builder()
.baseUrl("https://slack.com")
.addConverterFactory(GsonConverterFactory.create())
.build() //
.create(SlackApi.class);
}
@Override
protected void afterDefaultHandling(HeapDump heapDump, AnalysisResult result, String leakInfo) {
Log.e(TAG, "afterDefaultHandling " + leakInfo);
if (!result.leakFound || result.excludedLeak) {
Log.e(TAG, "!result.leakFound || result.excludedLeak");
return;
}
String name = classSimpleName(result.className);
if (!heapDump.referenceName.equals("")) {
name += "(" + heapDump.referenceName + ")";
}
String title = name + " has leaked5";
String initialComment = leakInfo.substring(0, leakInfo.indexOf("Details:", 0));
RequestBody file = RequestBody
.create(MediaType.parse("multipart/form-data"), heapDump.heapDumpFile);
MultipartBody.Part body =
MultipartBody.Part.createFormData("file", heapDump.heapDumpFile.getName(), file);
final Call<UploadFileResponse> call = slackApi.uploadFile(SlackApi.TOKEN,
body,
null,
heapDump.heapDumpFile.getName(), title, initialComment,
SlackApi.MEMORY_LEAK_CHANNEL);
call.enqueue(this);
}
@Override
public void onResponse(Call<UploadFileResponse> call,
Response<UploadFileResponse> response) {
Log.d(TAG, response.body().toString());
}
@Override
public void onFailure(Call<UploadFileResponse> call, Throwable t) {
Log.d(TAG, t.getLocalizedMessage());
}
/** See https://api.slack.com/ for documentation. */
public interface SlackApi {
String TOKEN = "YOUR_TOKEN";
String MEMORY_LEAK_CHANNEL = "YOUR_CHANNEL";
@Multipart
@POST("/api/files.upload")
Call<UploadFileResponse> uploadFile(
@Query("token") String token,
@Part MultipartBody.Part file, @Query("filetype") String filetype,
@Query("filename") String filename, @Query("title") String title,
@Query("initial_comment") String initialComment,
@Query("channels") String channels);
}
public static class UploadFileResponse {
boolean ok;
String error;
@Override
public String toString() {
return "UploadFileResponse{" +
"ok=" + ok +
", error='" + error + '\'' +
'}';
}
}
private static final String TAG = "LeakListenerService";
private static String classSimpleName(String className) {
int separator = className.lastIndexOf('.');
return separator == -1 ? className : className.substring(separator + 1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment