3535
3636import com .google .common .annotations .VisibleForTesting ;
3737import com .google .common .base .Preconditions ;
38+ import org .slf4j .Logger ;
39+ import org .slf4j .LoggerFactory ;
3840
3941import org .apache .hadoop .fs .azurebfs .contracts .exceptions .AbfsRestOperationException ;
4042import org .apache .hadoop .fs .azurebfs .contracts .exceptions .AzureBlobFileSystemException ;
5052 * The BlobFsOutputStream for Rest AbfsClient.
5153 */
5254public class AbfsOutputStream extends OutputStream implements Syncable , StreamCapabilities {
55+
5356 private final AbfsClient client ;
5457 private final String path ;
5558 private long position ;
@@ -80,6 +83,10 @@ public class AbfsOutputStream extends OutputStream implements Syncable, StreamCa
8083 = new ElasticByteBufferPool ();
8184
8285 private final Statistics statistics ;
86+ private final AbfsOutputStreamStatistics outputStreamStatistics ;
87+
88+ private static final Logger LOG =
89+ LoggerFactory .getLogger (AbfsOutputStream .class );
8390
8491 public AbfsOutputStream (
8592 final AbfsClient client ,
@@ -101,6 +108,7 @@ public AbfsOutputStream(
101108 this .buffer = byteBufferPool .getBuffer (false , bufferSize ).array ();
102109 this .bufferIndex = 0 ;
103110 this .writeOperations = new ConcurrentLinkedDeque <>();
111+ this .outputStreamStatistics = abfsOutputStreamContext .getStreamStatistics ();
104112
105113 this .maxConcurrentRequestCount = 4 * Runtime .getRuntime ().availableProcessors ();
106114
@@ -278,6 +286,9 @@ public synchronized void close() throws IOException {
278286 threadExecutor .shutdownNow ();
279287 }
280288 }
289+ if (LOG .isDebugEnabled ()) {
290+ LOG .debug ("Closing AbfsOutputStream " , toString ());
291+ }
281292 }
282293
283294 private synchronized void flushInternal (boolean isClose ) throws IOException {
@@ -296,16 +307,20 @@ private synchronized void writeCurrentBufferToService() throws IOException {
296307 if (bufferIndex == 0 ) {
297308 return ;
298309 }
310+ outputStreamStatistics .writeCurrentBuffer ();
299311
300312 final byte [] bytes = buffer ;
301313 final int bytesLength = bufferIndex ;
314+ outputStreamStatistics .bytesToUpload (bytesLength );
302315 buffer = byteBufferPool .getBuffer (false , bufferSize ).array ();
303316 bufferIndex = 0 ;
304317 final long offset = position ;
305318 position += bytesLength ;
306319
307320 if (threadExecutor .getQueue ().size () >= maxConcurrentRequestCount * 2 ) {
321+ long start = System .currentTimeMillis ();
308322 waitForTaskToComplete ();
323+ outputStreamStatistics .timeSpentTaskWait (start , System .currentTimeMillis ());
309324 }
310325
311326 final Future <Void > job = completionService .submit (new Callable <Void >() {
@@ -324,6 +339,11 @@ public Void call() throws Exception {
324339 }
325340 });
326341
342+ if (job .isCancelled ()) {
343+ outputStreamStatistics .uploadFailed (bytesLength );
344+ } else {
345+ outputStreamStatistics .uploadSuccessful (bytesLength );
346+ }
327347 writeOperations .add (new WriteOperation (job , offset , bytesLength ));
328348
329349 // Try to shrink the queue
@@ -388,6 +408,8 @@ private synchronized void shrinkWriteOperationQueue() throws IOException {
388408 writeOperations .peek ().task .get ();
389409 lastTotalAppendOffset += writeOperations .peek ().length ;
390410 writeOperations .remove ();
411+ // Incrementing statistics to indicate queue has been shrunk.
412+ outputStreamStatistics .queueShrunk ();
391413 }
392414 } catch (Exception e ) {
393415 if (e .getCause () instanceof AzureBlobFileSystemException ) {
@@ -435,4 +457,38 @@ private static class WriteOperation {
435457 public synchronized void waitForPendingUploads () throws IOException {
436458 waitForTaskToComplete ();
437459 }
460+
461+ /**
462+ * Getter method for AbfsOutputStream statistics.
463+ *
464+ * @return statistics for AbfsOutputStream.
465+ */
466+ @ VisibleForTesting
467+ public AbfsOutputStreamStatistics getOutputStreamStatistics () {
468+ return outputStreamStatistics ;
469+ }
470+
471+ /**
472+ * Getter to get the size of the task queue.
473+ *
474+ * @return the number of writeOperations in AbfsOutputStream.
475+ */
476+ @ VisibleForTesting
477+ public int getWriteOperationsSize () {
478+ return writeOperations .size ();
479+ }
480+
481+ /**
482+ * Appending AbfsOutputStream statistics to base toString().
483+ *
484+ * @return String with AbfsOutputStream statistics.
485+ */
486+ @ Override
487+ public String toString () {
488+ final StringBuilder sb = new StringBuilder (super .toString ());
489+ sb .append ("AbfsOuputStream@" ).append (this .hashCode ()).append ("){" );
490+ sb .append (outputStreamStatistics .toString ());
491+ sb .append ("}" );
492+ return sb .toString ();
493+ }
438494}
0 commit comments