
    iq                         d dl Z d dlZd dlZd dlmZ d dlmZmZ d dl  G d de j                  j                        Z
 G d d      Zy)	    N)datetime)OptionalList)*c                   .     e Zd ZdZ	 	 d fd	Zd Z xZS )FlushRotatingFileHandleruY  
    RotatingFileHandler, который при ротации:
    1. Сбрасывает текущий файл через callback (-> S3)
    2. Очищает файл
    3. Продолжает писать в тот же файл
    
    Никаких переименований, никаких .1/.2/.3 — один файл.
    c                 <    t         |   ||d||       || _        y )Nr   )maxBytesbackupCountencodingdelay)super__init__on_flush_callback)selffilenamer
   r   r   r   	__class__s         #./common/utils/attachment_logger.pyr   z!FlushRotatingFileHandler.__init__   s*     	H!"*% 	 	9!2    c                 8   | j                   r!| j                   j                          d| _         | j                  rqt        j                  j                  | j                        rHt        j                  j                  | j                        dkD  r	 | j                  | j                         t        | j                  d      5  	 ddd       | j                         | _         y# t        $ r#}t        j                  d| d       Y d}~]d}~ww xY w# 1 sw Y   NxY w)ud   Сохраняем файл как аттач, затем очищаем и пишем дальше.Nr   z+[FlushRotatingFileHandler] callback error: ERRORw)streamcloser   ospathexistsbaseFilenamegetsize	Exceptiongdebugopen_open)r   es     r   
doRolloverz#FlushRotatingFileHandler.doRollover   s     ;;KKDK !!bggnnT5F5F&Gwwt001A5X**4+<+<= $##S) 		 jjl ! XGGI!MwWWX	 	s$   C! D!	D*DDD)i   NFN)__name__
__module____qualname____doc__r   r&   __classcell__)r   s   @r   r   r   	   s     +7?C3#r   r   c            	           e Zd ZdZ	 	 ddedededefdZd Zd	ed
edee	   fdZ
d
efdZdedefdZdefdZdefdZdefdZddefdZdefdZd Zd Zd Zy)AttachmentLoggeru  
    Логгер, который пишет в один tmp-файл.
    При заполнении (max_size_mb) сбрасывает содержимое на S3 как CmfAttachment
    и продолжает писать в тот же файл.
    Nprefixmax_size_mbbase_log_name	max_filesc                    || _         g | _        d| _        || _        t	        j
                         j                  d      }| d| | _        t        j                  d|dddd	      }|j                  | _        |j                          t        | j                  |d
z  d
z  d| j                        | _        | j                  j!                  t#        j$                  dd             dt&        j(                  j+                  | j                         }t#        j,                  |      | _        | j.                  j0                  dd D ]-  }	| j.                  j3                  |	       |	j                          / | j.                  j5                  t"        j6                         | j.                  j9                  | j                         d| j.                  _        y)u  
        :param prefix: префикс tmp-файла
        :param max_size_mb: порог ротации в MB
        :param parent_obj: объект EVA для привязки аттачей
        :param base_log_name: базовое имя аттачей
        r   z%Y%m%d-%H%M_r   .logz/tmpFzutf-8)moder.   suffixdirdeleter   i   )r   r
   r   r   z'%(asctime)s %(levelname)-5s %(message)sz%Y-%m-%d %H:%M:%S)datefmtattachment_logger_N)
parent_objsaved_attachments_part_counterr1   r   nowstrftimer0   tempfileNamedTemporaryFilenamelog_pathr   r   
_on_rotatehandlersetFormatterlogging	Formatterr   r   basename	getLoggerloggerhandlersremoveHandlersetLevelINFO
addHandler	propagate)
r   r.   r/   r;   r0   r1   tstmplogger_namehs
             r   r   zAttachmentLogger.__init__9   s{    %=?"\\^$$]3 -at4 ))VFuw
 		 0]] 4'$."oo	
 	!!'"3"35'#
 	
 +277+;+;DMM+J*KL''4%%a( 	AKK%%a(GGI	 	W\\*t||, %r   c                 f   t        | j                        | j                  kD  rR| j                  j                  d      }	 |j	                  d       t        | j                        | j                  kD  rQyy# t
        $ r1}t        j                  d|j                   d| d       Y d}~Zd}~ww xY w)	uX   Удаляет самый старый аттач, если превышен лимит.r   T)forceu:   Ошибка удаления старого аттача z: WARNINGlevelN)	lenr<   r1   popr8   r    r!   r"   rB   )r   oldestr%   s      r   _cleanup_old_attachmentsz)AttachmentLogger._cleanup_old_attachmentsf   s    $(()DNN:++//2FzD) $(()DNN:  zTU[U`U`Taacdecfgoxyyzs   A6 6	B0?'B++B0rB   r   returnc                 B   | j                   syt        j                  | j                   |d      }|j                          t	        |d      5 }|j                  |j                         ddd       ddd       | j                  j                  |       |S # 1 sw Y   &xY w)u[   Создаёт CmfAttachment, заливает файл, возвращает объект.Nr4   )parentrB   	file_typerbF)make_previewbackup
mark_dirty)	r;   modelsCmfAttachmentsaver#   upload_filereadr<   append)r   rB   r   
attachmentfs        r   _upload_as_attachmentz&AttachmentLogger._upload_as_attachmentq   s    ))?? * 


 	$ 	B""1668%).5 # B	B 	%%j1	B 	Bs   $BBc                    | xj                   dz  c_         | j                   d| j                    d}	 | j                  ||       | j                          y# t        $ r$}t
        j                  d| d       Y d}~yd}~ww xY w)u]   Callback от хэндлера: файл заполнился — сохраняем на S3.   _partr4   u0   Ошибка загрузки лога на S3: r   rY   N)r=   r0   ro   r^   r    r!   r"   )r   r   rB   r%   s       r   rD   zAttachmentLogger._on_rotate   s    a$$%U4+=+=*>dC	[&&tT2))+ 	[GGFqcJRYGZZ	[s   "A 	BA>>BrZ   messagec                      t        | j                  |j                               |       t        j	                  ||       y )NrY   )getattrrK   lowerr!   r"   )r   rZ   rs   s      r   logzAttachmentLogger.log   s-    +U[[]+G4	u%r   c                 (    | j                  d|       y )NrO   rw   r   rs   s     r   infozAttachmentLogger.info   s    TXXfg%>r   c                 (    | j                  d|       y )NrX   ry   rz   s     r   warningzAttachmentLogger.warning   s    TXXi%Ar   c                 (    | j                  d|       y )Nr   ry   rz   s     r   errorzAttachmentLogger.error   s    TXXgw%?r   custom_namec                    | j                   j                          t        j                  j	                  | j
                        syt        j                  j                  | j
                        dk(  ry| xj                  dz  c_        |xs | j                   d| j                   d}	 | j                  || j
                        S # t        $ r$}t        j                  d| d       Y d}~yd}~ww xY w)	u   
        Сохраняет текущее содержимое файла на S3.
        Вызывать в конце процесса для последней порции.
        Nr   rq   rr   r4   uE   Ошибка загрузки финального лога на S3: r   rY   )rE   flushr   r   r   rC   r   r=   r0   ro   r    r!   r"   )r   r   rB   r%   s       r   flush_to_s3zAttachmentLogger.flush_to_s3   s    
 	ww~~dmm,77??4==)Q.aR!3!3 4E$:L:L9MTR	--dDMMBB 	GG[\][^_gnGo	s   (C 	C1C,,C1c                 (   t         j                  j                  | j                        r)t         j                  j	                  | j                        nd}t        |dz  d      | j                  j                  dz  | j                  | j                  dS )Nr   i      )current_size_mbr/   parts_savedcurrent_path)	r   r   r   rC   r   roundrE   r
   r=   )r   current_sizes     r   	get_statszAttachmentLogger.get_stats   si    9;9Vrwwt}}5\]$\[%A1E<<00K@-- MM	
 	
r   c                     | j                   j                          | j                   j                          t        j                  j                  | j                        r t        j                  | j                         yy)ub   Закрывает хэндлер. Не забудь вызвать flush_to_s3() до этого!N)rE   r   r   r   r   r   rC   unlinkr   s    r   r   zAttachmentLogger.close   sK    77>>$--(IIdmm$ )r   c                     | S N r   s    r   	__enter__zAttachmentLogger.__enter__   s    r   c                 D    | j                          | j                          y r   )r   r   )r   exc_typeexc_valexc_tbs       r   __exit__zAttachmentLogger.__exit__   s    

r   )   Ndata_logr   r   )r'   r(   r)   r*   strintr   r^   r   Anyro   rD   rw   r{   r}   r   r   dictr   r   r   r   r   r   r   r-   r-   2   s     8:TV+&s +& +&14+&NQ+&Zz# S Xc] &[s [& &s & ?C>AsA?S?s (
4 
%r   r-   )rG   r@   r   r   typingr   r   cmf.includerL   RotatingFileHandlerr   r-   r   r   r   <module>r      s<      	  ! &#w//CC &#RP Pr   