diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/common/ParameterConstants.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/common/ParameterConstants.java index 96bfaf27fd..4bc727cc37 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/common/ParameterConstants.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/common/ParameterConstants.java @@ -209,6 +209,7 @@ private ParameterConstants() { public final static String TRANSPORT_HTTP_BASIC_AUTH_PASSWORD = "http.basic.auth.password"; public final static String TRANSPORT_TYPE = "transport.type"; public final static String TRANSPORT_MAX_BYTES_TO_SYNC = "transport.max.bytes.to.sync"; + public final static String TRANSPORT_MAX_ERROR_MILLIS = "transport.max.error.millis"; public final static String CACHE_TIMEOUT_GROUPLETS_IN_MS = "cache.grouplets.time.ms"; public final static String CACHE_TIMEOUT_NODE_SECURITY_IN_MS = "cache.node.security.time.ms"; diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/io/DefaultOfflineClientListener.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/io/DefaultOfflineClientListener.java index dda439efd2..4ad5611b04 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/io/DefaultOfflineClientListener.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/io/DefaultOfflineClientListener.java @@ -44,20 +44,15 @@ public DefaultOfflineClientListener(IParameterService parameterService, } public void busy(Node remoteNode) { - log.info("Node '{}' was too busy to accept the connection", remoteNode.getNodeId()); } public void notAuthenticated(Node remoteNode) { - log.warn("Could not authenticate with node '{}'", remoteNode.getNodeId()); } public void unknownError(Node remoteNode, Exception ex) { } public void offline(Node remoteNode) { - log.warn("Failed to connect to the transport: {}", - (remoteNode.getSyncUrl() == null ? parameterService.getRegistrationUrl() : remoteNode - .getSyncUrl())); } public void syncDisabled(Node remoteNode) { @@ -70,7 +65,6 @@ public void syncDisabled(Node remoteNode) { } public void registrationRequired(Node remoteNode) { - log.warn("Registration is required before this operation can complete"); } } diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/AbstractOfflineDetectorService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/AbstractOfflineDetectorService.java index aeeabf1c6d..c32b30ab1d 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/AbstractOfflineDetectorService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/AbstractOfflineDetectorService.java @@ -24,9 +24,13 @@ import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.lang.exception.ExceptionUtils; +import org.jumpmind.exception.HttpException; +import org.jumpmind.symmetric.common.ParameterConstants; import org.jumpmind.symmetric.db.ISymmetricDialect; import org.jumpmind.symmetric.io.IOfflineClientListener; import org.jumpmind.symmetric.model.Node; @@ -45,15 +49,21 @@ * Abstract service that provides help methods for detecting offline status. */ public abstract class AbstractOfflineDetectorService extends AbstractService implements IOfflineDetectorService { - + protected IExtensionService extensionService; + private Map transportErrorTimeByNode = new HashMap(); + public AbstractOfflineDetectorService(IParameterService parameterService, ISymmetricDialect symmetricDialect, IExtensionService extensionService) { super(parameterService, symmetricDialect); this.extensionService = extensionService; } + protected void fireOnline(Node remoteNode, RemoteNodeStatus status) { + transportErrorTimeByNode.remove(remoteNode.getNodeId()); + } + protected void fireOffline(Exception error, Node remoteNode, RemoteNodeStatus status) { String syncUrl = remoteNode.getSyncUrl() == null ? parameterService.getRegistrationUrl() : remoteNode .getSyncUrl(); @@ -62,23 +72,46 @@ protected void fireOffline(Exception error, Node remoteNode, RemoteNodeStatus st cause = error; } if (isOffline(error)) { - log.warn("Could not communicate with {} at {} because: {}", new Object[] {remoteNode, syncUrl, cause.getMessage()}); + String reason = cause.getMessage(); + if (reason == null) { + reason = cause.getClass().getName(); + } + if (shouldLogTransportError(remoteNode.getNodeId())) { + log.warn("Could not communicate with {} at {} because: {}", new Object[] {remoteNode, syncUrl, reason}); + } else { + log.info("Could not communicate with {} at {} because: {}", new Object[] {remoteNode, syncUrl, reason}); + } status.setStatus(Status.OFFLINE); } else if (isServiceUnavailable(error)) { - log.info("{} at {} was unavailable", new Object[] {remoteNode, syncUrl}); + if (shouldLogTransportError(remoteNode.getNodeId())) { + log.warn("{} at {} was unavailable.", new Object[] {remoteNode, syncUrl}); + } else { + log.info("{} at {} was unavailable. It may be starting up.", new Object[] {remoteNode, syncUrl}); + } status.setStatus(Status.OFFLINE); } else if (isBusy(error)) { - log.info("{} at {} was busy", new Object[] {remoteNode, syncUrl}); + if (shouldLogTransportError(remoteNode.getNodeId())) { + log.warn("{} at {} was busy", new Object[] {remoteNode, syncUrl}); + } else { + log.info("{} at {} was busy", new Object[] {remoteNode, syncUrl}); + } status.setStatus(Status.BUSY); } else if (isNotAuthenticated(error)) { - log.info("{} at {} was not authorized", new Object[] {remoteNode, syncUrl}); + log.warn("{} at {} was not authorized", new Object[] {remoteNode, syncUrl}); status.setStatus(Status.NOT_AUTHORIZED); } else if (isSyncDisabled(error)) { - log.info("Sync was not enabled for {} at {}", new Object[] {remoteNode, syncUrl}); + log.warn("Sync was not enabled for {} at {}", new Object[] {remoteNode, syncUrl}); status.setStatus(Status.SYNC_DISABLED); } else if (isRegistrationRequired(error)) { - log.info("Registration was not open at {}", new Object[] {remoteNode, syncUrl}); + log.warn("Registration was not open at {}", new Object[] {remoteNode, syncUrl}); status.setStatus(Status.REGISTRATION_REQUIRED); + } else if (getHttpException(error) != null) { + HttpException http = getHttpException(error); + if (shouldLogTransportError(remoteNode.getNodeId())) { + log.warn("Could not communicate with node '{}' at {} because it returned HTTP code {}", remoteNode, syncUrl, http.getCode()); + } else { + log.info("Could not communicate with node '{}' at {} because it returned HTTP code {}", remoteNode, syncUrl, http.getCode()); + } } else { log.warn(String.format("Could not communicate with node '%s' at %s because of unexpected error", remoteNode, syncUrl), error); status.setStatus(Status.UNKNOWN_ERROR); @@ -104,6 +137,16 @@ protected void fireOffline(Exception error, Node remoteNode, RemoteNodeStatus st } } + protected boolean shouldLogTransportError(String nodeId) { + long maxErrorMillis = parameterService.getLong(ParameterConstants.TRANSPORT_MAX_ERROR_MILLIS, 300000); + Long errorTime = transportErrorTimeByNode.get(nodeId); + if (errorTime == null) { + errorTime = System.currentTimeMillis(); + transportErrorTimeByNode.put(nodeId, errorTime); + } + return System.currentTimeMillis() - errorTime >= maxErrorMillis; + } + /** * Check to see if the {@link Exception} was caused by an offline scenario. * @@ -179,4 +222,18 @@ protected boolean isRegistrationRequired(Exception ex) { } return registrationRequired; } + + protected HttpException getHttpException(Exception ex) { + HttpException exception = null; + if (ex != null) { + Throwable cause = ExceptionUtils.getRootCause(ex); + if (cause instanceof HttpException) { + exception = (HttpException) cause; + } else if (ex instanceof HttpException) { + exception = (HttpException) ex; + } + } + return exception; + } + } \ No newline at end of file diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/AcknowledgeService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/AcknowledgeService.java index 3f60465ada..1c7bf00930 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/AcknowledgeService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/AcknowledgeService.java @@ -110,9 +110,8 @@ public BatchAckResult ack(final BatchAck batch) { } if (status == Status.ER) { - log.error( - "The outgoing batch {} failed: {}", - outgoingBatch.getNodeBatchId(), batch.getSqlMessage() != null ? ". " + batch.getSqlMessage() : ""); + log.error("The outgoing batch {} failed: {}{}", outgoingBatch.getNodeBatchId(), + (batch.getSqlCode() != 0 ? "[" + batch.getSqlState() + "," + batch.getSqlCode() + "] " : ""), batch.getSqlMessage()); RouterStats routerStats = engine.getStatisticManager().getRouterStatsByBatch(batch.getBatchId()); if (routerStats != null) { log.info("Router stats for batch " + outgoingBatch.getBatchId() + ": " + routerStats.toString()); diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataExtractorService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataExtractorService.java index f186f6b8fa..a7cba8aea4 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataExtractorService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataExtractorService.java @@ -693,18 +693,18 @@ public FutureOutgoingBatch call() throws Exception { } outgoingBatchService.updateOutgoingBatch(currentBatch); - if (isStreamClosedByClient(e)) { - log.warn( - "Failed to transport batch {}. The stream was closed by the client. There is a good chance that a previously sent batch errored out and the stream was closed or there was a network error. The error was: {}", - currentBatch, getRootMessage(e)); - } else { + if (!isStreamClosedByClient(e)) { if (e instanceof ProtocolException) { IStagedResource resource = getStagedResource(currentBatch); if (resource != null) { resource.delete(); } } - log.error("Failed to extract batch {}", currentBatch, e); + if (e.getCause() instanceof InterruptedException) { + log.info("Extract of batch {} was interrupted", currentBatch); + } else { + log.error("Failed to extract batch {}", currentBatch, e); + } } processInfo.setStatus(ProcessInfo.Status.ERROR); } else { diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataLoaderService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataLoaderService.java index 6a85413906..01885a82ae 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataLoaderService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataLoaderService.java @@ -139,8 +139,6 @@ */ public class DataLoaderService extends AbstractService implements IDataLoaderService { - private static final int MAX_NETWORK_ERROR_FOR_LOGGING = 5; - private IIncomingBatchService incomingBatchService; private IConfigurationService configurationService; @@ -169,8 +167,6 @@ public class DataLoaderService extends AbstractService implements IDataLoaderSer private Date lastUpdateTime; - private Map errorCountByNode = new HashMap(); - public DataLoaderService(ISymmetricEngine engine) { super(engine.getParameterService(), engine.getSymmetricDialect()); this.incomingBatchService = engine.getIncomingBatchService(); @@ -342,13 +338,6 @@ public void loadDataFromPull(Node remote, RemoteNodeStatus status) throws IOExce log.error("", e); } throw e; - } catch (ServiceUnavailableException e) { - if (remote.getNodeId() == null) { - log.info("Service is unavailable for registration with remote node. It may be starting up."); - } else { - log.info("Service is unavailable for remote node " + remote.getNodeGroupId() + "-" + remote.getNodeId() + - ". It may be starting up."); - } } } @@ -408,6 +397,8 @@ public void loadDataFromPush(Node sourceNode, String channelId, InputStream in, processInfo.setStatus(ProcessInfo.Status.ERROR); if (e instanceof RuntimeException) { throw (RuntimeException) e; + } else if (e instanceof IOException) { + throw (IOException) e; } throw new RuntimeException(e); } @@ -534,10 +525,9 @@ protected IDataWriter chooseDataWriter(Batch batch) { }; processor.process(ctx); } - errorCountByNode.remove(sourceNode.getNodeId()); } catch (Throwable ex) { error = ex; - logAndRethrow(sourceNode, ex); + logAndRethrow(ex); } finally { transport.close(); @@ -549,52 +539,27 @@ protected IDataWriter chooseDataWriter(Batch batch) { return listener.getBatchesProcessed(); } - protected void logAndRethrow(Node remoteNode, Throwable ex) throws IOException { + protected void logAndRethrow(Throwable ex) throws IOException { if (ex instanceof RegistrationRequiredException) { throw (RegistrationRequiredException) ex; } else if (ex instanceof ConnectException) { throw (ConnectException) ex; } else if (ex instanceof UnknownHostException) { - log.warn("Could not connect to the transport because the host was unknown: '{}'", - ex.getMessage()); throw (UnknownHostException) ex; } else if (ex instanceof RegistrationNotOpenException) { - log.warn("Registration attempt failed. Registration was not open"); + throw (RegistrationNotOpenException) ex; } else if (ex instanceof ConnectionRejectedException) { throw (ConnectionRejectedException) ex; } else if (ex instanceof ServiceUnavailableException) { throw (ServiceUnavailableException) ex; } else if (ex instanceof AuthenticationException) { - log.warn("Could not authenticate with node '{}'", - remoteNode != null ? remoteNode.getNodeId() : "?"); throw (AuthenticationException) ex; } else if (ex instanceof SyncDisabledException) { - log.warn("Synchronization is disabled on the server node"); throw (SyncDisabledException) ex; } else if (ex instanceof IOException) { - Integer errorCount = errorCountByNode.get(remoteNode.getNodeId()); - if (errorCount == null) { - errorCount = 1; - } - if (errorCount >= MAX_NETWORK_ERROR_FOR_LOGGING) { - if (ex.getMessage() != null && !ex.getMessage().startsWith("http")) { - log.error("Failed while reading batch because: {}", ex.getMessage()); - } else { - log.error("Failed while reading batch because: {}", ex.getMessage(), ex); - } - } else { - if (ex.getMessage() != null && !ex.getMessage().startsWith("http")) { - log.info("Failed while reading batch because: {}", ex.getMessage()); - } else { - log.info("Failed while reading batch because: {}", ex.getMessage(), ex); - } - } - errorCountByNode.put(remoteNode.getNodeId(), errorCount + 1); throw (IOException) ex; - } else { - if (!(ex instanceof ConflictException || ex instanceof SqlException)) { - log.error("Failed while parsing batch", ex); - } + } else if (!(ex instanceof ConflictException) && !(ex instanceof SqlException)) { + log.error("Failed while parsing batch", ex); } } diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/PullService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/PullService.java index 883e5caffe..8e06242efe 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/PullService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/PullService.java @@ -20,10 +20,6 @@ */ package org.jumpmind.symmetric.service.impl; -import java.io.IOException; -import java.net.ConnectException; -import java.net.SocketException; -import java.net.UnknownHostException; import java.util.List; import org.apache.commons.lang.StringUtils; @@ -45,7 +41,6 @@ import org.jumpmind.symmetric.service.IParameterService; import org.jumpmind.symmetric.service.IPullService; import org.jumpmind.symmetric.service.IRegistrationService; -import org.jumpmind.symmetric.transport.OfflineException; /** * @see IPullService @@ -116,63 +111,43 @@ synchronized public RemoteNodeStatuses pullData(boolean force) { public void execute(NodeCommunication nodeCommunication, RemoteNodeStatus status) { Node node = nodeCommunication.getNode(); - if (StringUtils.isNotBlank(node.getSyncUrl()) || - !parameterService.isRegistrationServer()) { - int pullCount = 0; - long batchesProcessedCount = 0; - do { - batchesProcessedCount = status.getBatchesProcessed(); - pullCount++; - log.debug("Pull requested for {}", node.toString()); - if (pullCount > 1) { - log.info("Immediate pull requested while in reload mode"); - } - - try { + if (StringUtils.isNotBlank(node.getSyncUrl()) || !parameterService.isRegistrationServer()) { + int pullCount = 0; + long batchesProcessedCount = 0; + do { + batchesProcessedCount = status.getBatchesProcessed(); + pullCount++; + log.debug("Pull requested for {}", node.toString()); + if (pullCount > 1) { + log.info("Immediate pull requested while in reload mode"); + } + + try { dataLoaderService.loadDataFromPull(node, status); - } catch (ConnectException ex) { - log.warn( - "Failed to connect to the transport: {}", - (node.getSyncUrl() == null ? parameterService.getRegistrationUrl() : node - .getSyncUrl())); - fireOffline(ex, node, status); - } catch (OfflineException ex) { - fireOffline(ex, node, status); - } catch (UnknownHostException ex) { - fireOffline(ex, node, status); - } catch (SocketException ex) { - log.warn("{}", ex.getMessage()); - fireOffline(ex, node, status); - } catch (IOException ex) { - log.error("An IO exception happened while attempting to pull data", ex); + fireOnline(node, status); + } catch (Exception ex) { fireOffline(ex, node, status); } - - if (!status.failed() && - (status.getDataProcessed() > 0 || status.getBatchesProcessed() > 0)) { - log.info( - "Pull data received from {} {}. {} rows and {} batches were processed", - new Object[] { node.toString(), - "on channel thread " + nodeCommunication.getQueue(), - status.getDataProcessed(), - status.getBatchesProcessed() }); - } else if (status.failed()) { - log.info( - "There was a failure while pulling data from {} {}. {} rows and {} batches were processed", - new Object[] { node.toString(), - "on channel thread " + nodeCommunication.getQueue(), - status.getDataProcessed(), - status.getBatchesProcessed() }); - } - /* - * Re-pull immediately if we are in the middle of an initial - * load so that the initial load completes as quickly as - * possible. - */ - } while (nodeService.isDataLoadStarted() && !status.failed() - && status.getBatchesProcessed() > batchesProcessedCount); - + if (!status.failed() && (status.getDataProcessed() > 0 || status.getBatchesProcessed() > 0)) { + log.info( + "Pull data received from {} {}. {} rows and {} batches were processed", + new Object[] { node.toString(), "on channel thread " + nodeCommunication.getQueue(), + status.getDataProcessed(), status.getBatchesProcessed() }); + + } else if (status.failed()) { + log.debug( + "There was a failure while pulling data from {} {}. {} rows and {} batches were processed", + new Object[] { node.toString(), "on channel thread " + nodeCommunication.getQueue(), + status.getDataProcessed(), status.getBatchesProcessed() }); + } + /* + * Re-pull immediately if we are in the middle of an initial + * load so that the initial load completes as quickly as + * possible. + */ + } while (nodeService.isDataLoadStarted() && !status.failed() + && status.getBatchesProcessed() > batchesProcessedCount); } else { log.warn("Cannot pull node '{}' in the group '{}'. The sync url is blank", node.getNodeId(), node.getNodeGroupId()); diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/PushService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/PushService.java index 121d285fc6..0571fc241c 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/PushService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/PushService.java @@ -165,7 +165,7 @@ public void execute(NodeCommunication nodeCommunication, RemoteNodeStatus status new Object[] { node, status.getDataProcessed(), status.getBatchesProcessed()}); } else if (status.failed()) { - log.info( + log.debug( "There was a failure while pushing data to {}. {} data and {} batches were processed", new Object[] { node, status.getDataProcessed(), status.getBatchesProcessed()}); @@ -207,8 +207,9 @@ private void pushToNode(Node remote, RemoteNodeStatus status) { } if (processInfo.getStatus() != Status.ERROR) { - processInfo.setStatus(Status.OK); + processInfo.setStatus(Status.OK); } + fireOnline(remote, status); } catch (Exception ex) { processInfo.setStatus(Status.ERROR); fireOffline(ex, remote, status); diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/transport/http/HttpOutgoingTransport.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/transport/http/HttpOutgoingTransport.java index 4987764e34..11c3eb0d05 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/transport/http/HttpOutgoingTransport.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/transport/http/HttpOutgoingTransport.java @@ -32,6 +32,7 @@ import java.util.zip.GZIPOutputStream; import org.apache.commons.io.IOUtils; +import org.jumpmind.exception.HttpException; import org.jumpmind.exception.IoException; import org.jumpmind.symmetric.io.IoConstants; import org.jumpmind.symmetric.model.ChannelMap; @@ -290,7 +291,7 @@ private void analyzeResponseCode(int code) throws IOException { } else if (WebConstants.REGISTRATION_REQUIRED == code) { throw new RegistrationRequiredException(); } else if (200 != code) { - throw new IoException("Received an unexpected response code of " + code + " from the server"); + throw new HttpException(code, "Received an unexpected response code of " + code + " from the server"); } } diff --git a/symmetric-core/src/main/resources/symmetric-default.properties b/symmetric-core/src/main/resources/symmetric-default.properties index 96041898b7..f7b4c001d8 100644 --- a/symmetric-core/src/main/resources/symmetric-default.properties +++ b/symmetric-core/src/main/resources/symmetric-default.properties @@ -351,6 +351,14 @@ transport.type=http # Tags: transport transport.max.bytes.to.sync=1048576 +# Networks errors will be logged at INFO level since they are retried. +# After the maximum number of millis for network errors that continue in succession, the logging +# switches to WARN level. +# +# DatabaseOverridable: true +# Tags: transport +transport.max.error.millis=300000 + # This indicates whether this node engine should be started when the instance is restarted # # DatabaseOverridable: true diff --git a/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriter.java b/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriter.java index 651fb64656..a1ca693d62 100644 --- a/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriter.java +++ b/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriter.java @@ -22,6 +22,7 @@ import java.io.StringReader; import java.lang.reflect.Method; +import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.Arrays; @@ -640,7 +641,7 @@ private void removeExcludedColumns(Conflict conflict, @Override protected void logFailureDetails(Throwable e, CsvData data, boolean logLastDmlDetails) { StringBuilder failureMessage = new StringBuilder(); - failureMessage.append("Failed to process a "); + failureMessage.append("Failed to process "); failureMessage.append(data.getDataEventType().toString().toLowerCase()); failureMessage.append(" event in batch "); failureMessage.append(batch.getBatchId()); @@ -660,6 +661,13 @@ protected void logFailureDetails(Throwable e, CsvData data, boolean logLastDmlDe failureMessage.append(Arrays.toString(this.currentDmlStatement.getTypes())); failureMessage.append("\n"); } + + if (logLastDmlDetails && e instanceof SqlException && e.getCause() instanceof SQLException) { + SQLException se = (SQLException) e.getCause(); + failureMessage.append("Failed sql state and code: ").append(se.getSQLState()); + failureMessage.append(" (").append(se.getErrorCode()).append(")"); + failureMessage.append("\n"); + } data.writeCsvDataDetails(failureMessage); diff --git a/symmetric-util/src/main/java/org/jumpmind/exception/HttpException.java b/symmetric-util/src/main/java/org/jumpmind/exception/HttpException.java new file mode 100644 index 0000000000..8e79ca56d8 --- /dev/null +++ b/symmetric-util/src/main/java/org/jumpmind/exception/HttpException.java @@ -0,0 +1,37 @@ +/** + * Licensed to JumpMind Inc under one or more contributor + * license agreements. See the NOTICE file distributed + * with this work for additional information regarding + * copyright ownership. JumpMind Inc licenses this file + * to you under the GNU General Public License, version 3.0 (GPLv3) + * (the "License"); you may not use this file except in compliance + * with the License. + * + * You should have received a copy of the GNU General Public License, + * version 3.0 (GPLv3) along with this library; if not, see + * . + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jumpmind.exception; + +public class HttpException extends IoException { + + private static final long serialVersionUID = 1L; + + private int code; + + public HttpException(int code, String message) { + super(message); + this.code = code; + } + + public int getCode() { + return code; + } +} diff --git a/symmetric-util/src/main/java/org/jumpmind/util/AppUtils.java b/symmetric-util/src/main/java/org/jumpmind/util/AppUtils.java index 00cdd5d255..adbb03e8c5 100644 --- a/symmetric-util/src/main/java/org/jumpmind/util/AppUtils.java +++ b/symmetric-util/src/main/java/org/jumpmind/util/AppUtils.java @@ -102,7 +102,7 @@ public static String getHostName() { } } catch (Exception ex) { - log.warn("", ex); + log.info("Unable to lookup hostname: " + ex.getMessage()); } } return hostName;