code: public static void sendError(final Throwable throwable, final String description, final String extraData) {
  		if (!isConversationQueue()) {
  			dispatchOnConversationQueue(new DispatchTask() {
  				@Override
  				protected void execute() {
  					sendError(throwable, description, extraData);
  				}
  			});
  			return;
  		}
  
  		EventPayload.EventLabel type = EventPayload.EventLabel.error;
  		try {
  			JSONObject data = new JSONObject();
  			data.put("thread", Thread.currentThread().getName());
  			if (throwable != null) {
  				JSONObject exception = new JSONObject();
  				exception.put("message", throwable.getMessage());
  				exception.put("stackTrace", Util.stackTraceAsString(throwable));
  				data.put(KEY_EXCEPTION, exception);
  			}
  			if (description != null) {
  				data.put("description", description);
  			}
  			if (extraData != null) {
  				data.put("extraData", extraData);
  			}
  			Configuration config = Configuration.load();
  			if (config.isMetricsEnabled()) {
  				ApptentiveLog.v(UTIL, "Sending Error Metric: %s, data: %s", type.getLabelName(), data.toString());
  				EventPayload event = new EventPayload(type.getLabelName(), data);
  				sendEvent(event);
  			}
  		} catch (Exception e) {
  			// Since this is the last place in Apptentive code we can catch exceptions, we must catch all other Exceptions to
  			// prevent the app from crashing.
  			ApptentiveLog.w(UTIL, e, "Error creating Error Metric. Nothing we can do but log this.");
  		}
  	}
docs: Used for internal error reporting when we intercept a Throwable that may have otherwise caused a crash.
  
  @param throwable   An optional throwable that was caught, and which we want to log.
  @param description An optional description of what happened.
  @param extraData   Any extra data that may have contributed to the Throwable being thrown.