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