diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/contracts/exceptions/AbfsRestOperationException.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/contracts/exceptions/AbfsRestOperationException.java index 149f916c0a..36f7589f16 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/contracts/exceptions/AbfsRestOperationException.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/contracts/exceptions/AbfsRestOperationException.java @@ -81,13 +81,23 @@ public class AbfsRestOperationException extends AzureBlobFileSystemException { } private static String formatMessage(final AbfsHttpOperation abfsHttpOperation) { + // HEAD request response doesn't have StorageErrorCode, StorageErrorMessage. + if (abfsHttpOperation.getMethod().equals("HEAD")) { + return String.format( + "Operation failed: \"%1$s\", %2$s, HEAD, %3$s", + abfsHttpOperation.getStatusDescription(), + abfsHttpOperation.getStatusCode(), + abfsHttpOperation.getUrl().toString()); + } + return String.format( - "%1$s %2$s%nStatusCode=%3$s%nStatusDescription=%4$s%nErrorCode=%5$s%nErrorMessage=%6$s", - abfsHttpOperation.getMethod(), - abfsHttpOperation.getUrl().toString(), - abfsHttpOperation.getStatusCode(), - abfsHttpOperation.getStatusDescription(), - abfsHttpOperation.getStorageErrorCode(), - abfsHttpOperation.getStorageErrorMessage()); + "Operation failed: \"%1$s\", %2$s, %3$s, %4$s, %5$s, \"%6$s\"", + abfsHttpOperation.getStatusDescription(), + abfsHttpOperation.getStatusCode(), + abfsHttpOperation.getMethod(), + abfsHttpOperation.getUrl().toString(), + abfsHttpOperation.getStorageErrorCode(), + // Remove break line to ensure the request id and timestamp can be shown in console. + abfsHttpOperation.getStorageErrorMessage().replaceAll("\\n", " ")); } } \ No newline at end of file diff --git a/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAbfsRestOperationException.java b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAbfsRestOperationException.java new file mode 100644 index 0000000000..ff88b0243f --- /dev/null +++ b/hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAbfsRestOperationException.java @@ -0,0 +1,75 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.hadoop.fs.azurebfs; + +import java.io.IOException; + +import org.apache.hadoop.fs.FileStatus; +import org.apache.hadoop.fs.Path; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Verify the AbfsRestOperationException error message format. + * */ +public class ITestAbfsRestOperationException extends AbstractAbfsIntegrationTest{ + public ITestAbfsRestOperationException() throws Exception { + super(); + } + + @Test + public void testAbfsRestOperationExceptionFormat() throws IOException { + final AzureBlobFileSystem fs = getFileSystem(); + Path nonExistedFilePath1 = new Path("nonExistedPath1"); + Path nonExistedFilePath2 = new Path("nonExistedPath2"); + try { + FileStatus fileStatus = fs.getFileStatus(nonExistedFilePath1); + } catch (Exception ex) { + String errorMessage = ex.getLocalizedMessage(); + String[] errorFields = errorMessage.split(","); + + Assert.assertEquals(4, errorFields.length); + // Check status message, status code, HTTP Request Type and URL. + Assert.assertEquals("Operation failed: \"The specified path does not exist.\"", errorFields[0].trim()); + Assert.assertEquals("404", errorFields[1].trim()); + Assert.assertEquals("HEAD", errorFields[2].trim()); + Assert.assertTrue(errorFields[3].trim().startsWith("http")); + } + + try { + fs.listFiles(nonExistedFilePath2, false); + } catch (Exception ex) { + // verify its format + String errorMessage = ex.getLocalizedMessage(); + String[] errorFields = errorMessage.split(","); + + Assert.assertEquals(6, errorFields.length); + // Check status message, status code, HTTP Request Type and URL. + Assert.assertEquals("Operation failed: \"The specified path does not exist.\"", errorFields[0].trim()); + Assert.assertEquals("404", errorFields[1].trim()); + Assert.assertEquals("GET", errorFields[2].trim()); + Assert.assertTrue(errorFields[3].trim().startsWith("http")); + // Check storage error code and storage error message. + Assert.assertEquals("PathNotFound", errorFields[4].trim()); + Assert.assertTrue(errorFields[5].contains("RequestId") + && errorFields[5].contains("Time")); + } + } +} \ No newline at end of file