U
    M8cuP                     @   s   d dl Z d dlZd dlZd dlZd dlmZmZmZ d dlm	Z
 eeZG dd dZG dd dZG dd	 d	ZG d
d deZG dd deZG dd dZG dd dZdS )    N)ensure_bytesensure_unicodeurlparse)EXCEPTION_MAPc                   @   s2   e Zd ZdddddgZdd Zdd	 Zd
d ZdS )Monitorzbefore-parameter-buildzrequest-createdzresponse-receivedz
after-callzafter-call-errorc                 C   s   || _ || _dS )zAbstraction for monitoring clients API calls

        :param adapter: An adapter that takes event emitter events
            and produces monitor events

        :param publisher: A publisher for generated monitor events
        N)_adapter
_publisher)selfadapterZ	publisher r   7/tmp/pip-unpacked-wheel-ozje0y8b/botocore/monitoring.py__init__!   s    zMonitor.__init__c                 C   s   | j D ]}||| j qdS )z(Register an event emitter to the monitorN)_EVENTS_TO_REGISTERZregister_lastcapture)r	   Zevent_emitterZevent_to_registerr   r   r   register,   s    
zMonitor.registerc              
   K   s\   z"| j ||}|r | j| W n4 tk
rV } ztjd||dd W 5 d}~X Y nX dS )zCaptures an incoming event from the event emitter

        It will feed an event emitter event to the monitor's adaptor to create
        a monitor event and then publish that event to the monitor's publisher.
        z:Exception %s raised by client monitor in handling event %sT)exc_infoN)r   feedr   publish	Exceptionloggerdebug)r	   
event_namepayloadZmonitor_eventer   r   r   r   1   s    zMonitor.captureN)__name__
__module____qualname__r   r   r   r   r   r   r   r   r      s   r   c                   @   sr   e Zd ZejfddZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd ZdS )MonitorEventAdapterc                 C   s
   || _ dS )zAdapts event emitter events to produce monitor events

        :type time: callable
        :param time: A callable that produces the current time
        N)_time)r	   timer   r   r   r   E   s    zMonitorEventAdapter.__init__c                 C   s   |  |f |S )a  Feed an event emitter event to generate a monitor event

        :type emitter_event_name: str
        :param emitter_event_name: The name of the event emitted

        :type emitter_payload: dict
        :param emitter_payload: The payload to associated to the event
            emitted

        :rtype: BaseMonitorEvent
        :returns: A monitor event based on the event emitter events
            fired
        )_get_handler)r	   Zemitter_event_nameZemitter_payloadr   r   r   r   M   s    zMonitorEventAdapter.feedc                 C   s    t | d|dd dd S )NZ_handle_.r   -_)getattrsplitreplace)r	   r   r   r   r   r    ]   s     z MonitorEventAdapter._get_handlerc                 K   s    t |jj|j|  d|d< d S )Nservice	operation	timestampcurrent_api_call_event)APICallEventZservice_modelZ
service_idZ	wire_name_get_current_time)r	   modelcontextkwargsr   r   r   _handle_before_parameter_buildb   s
    z2MonitorEventAdapter._handle_before_parameter_buildc                 K   s6   |j }|d j|  d}|j|_|j|_||d< d S )Nr+   )r*   current_api_call_attempt_event)r/   new_api_call_attemptr-   headersrequest_headersurl)r	   requestr0   r/   Znew_attempt_eventr   r   r   _handle_request_createdi   s    z+MonitorEventAdapter._handle_request_createdc                 K   sR   | d}| ||_|d k	rH|d d |_|d d |_|d|_n||_|S )Nr2   ResponseMetadataZHTTPStatusCodeZHTTPHeadersError)pop_get_latencylatencyhttp_status_coderesponse_headersgetparsed_errorwire_exception)r	   Zparsed_responser/   	exceptionr0   attempt_eventr   r   r   _handle_response_receivedr   s     
z-MonitorEventAdapter._handle_response_receivedc                 K   s    |d  dd|d _| |S )Nr9   ZMaxAttemptsReachedFr+   )r@   retries_exceeded_complete_api_call)r	   r/   parsedr0   r   r   r   _handle_after_call   s     
z&MonitorEventAdapter._handle_after_callc                 K   s   |  ||d _| |S Nr+   )_is_retryable_exceptionrF   rG   )r	   r/   rC   r0   r   r   r   _handle_after_call_error   s
    z,MonitorEventAdapter._handle_after_call_errorc                 C   s   t |ttd S )NZGENERAL_CONNECTION_ERROR)
isinstancetupleRETRYABLE_EXCEPTIONS)r	   rC   r   r   r   rK      s     
z+MonitorEventAdapter._is_retryable_exceptionc                 C   s   | d}| ||_|S rJ   )r;   r<   r=   )r	   r/   Z
call_eventr   r   r   rG      s    
z&MonitorEventAdapter._complete_api_callc                 C   s   |   |j S N)r-   r*   r	   eventr   r   r   r<      s    z MonitorEventAdapter._get_latencyc                 C   s   t |  d S )Ni  )intr   r	   r   r   r   r-      s    z%MonitorEventAdapter._get_current_timeN)r   r   r   r   r   r   r    r1   r8   rE   rI   rL   rK   rG   r<   r-   r   r   r   r   r   D   s   	
r   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )BaseMonitorEventc                 C   s   || _ || _|| _dS )a  Base monitor event

        :type service: str
        :param service: A string identifying the service associated to
            the event

        :type operation: str
        :param operation: A string identifying the operation of service
            associated to the event

        :type timestamp: int
        :param timestamp: Epoch time in milliseconds from when the event began
        Nr'   )r	   r(   r)   r*   r   r   r   r      s    zBaseMonitorEvent.__init__c                 C   s   | j j d| jdS )N())	__class__r   __dict__rT   r   r   r   __repr__   s    zBaseMonitorEvent.__repr__c                 C   s   t || jr| j|jkS dS )NF)rM   rX   rY   )r	   otherr   r   r   __eq__   s    zBaseMonitorEvent.__eq__N)r   r   r   r   rZ   r\   r   r   r   r   rU      s   rU   c                       s&   e Zd Zd fdd	Zdd Z  ZS )r,   NFc                    s6   t  j|||d || _|| _|dkr,g | _|| _dS )a  Monitor event for a single API call

        This event corresponds to a single client method call, which includes
        every HTTP requests attempt made in order to complete the client call

        :type service: str
        :param service: A string identifying the service associated to
            the event

        :type operation: str
        :param operation: A string identifying the operation of service
            associated to the event

        :type timestamp: int
        :param timestamp: Epoch time in milliseconds from when the event began

        :type latency: int
        :param latency: The time in milliseconds to complete the client call

        :type attempts: list
        :param attempts: The list of APICallAttempts associated to the
            APICall

        :type retries_exceeded: bool
        :param retries_exceeded: True if API call exceeded retries. False
            otherwise
        r'   N)superr   r=   attemptsrF   )r	   r(   r)   r*   r=   r^   rF   rX   r   r   r      s    $  zAPICallEvent.__init__c                 C   s"   t | j| j|d}| j| |S )zInstantiates APICallAttemptEvent associated to the APICallEvent

        :type timestamp: int
        :param timestamp: Epoch time in milliseconds to associate to the
            APICallAttemptEvent
        r'   )APICallAttemptEventr(   r)   r^   append)r	   r*   rD   r   r   r   r3      s      z!APICallEvent.new_api_call_attempt)NNF)r   r   r   r   r3   __classcell__r   r   r_   r   r,      s
      -r,   c                       s   e Zd Zd fdd	Z  ZS )r`   Nc                    s@   t  j|||d || _|| _|| _|| _|| _|	| _|
| _dS )a  Monitor event for a single API call attempt

        This event corresponds to a single HTTP request attempt in completing
        the entire client method call.

        :type service: str
        :param service: A string identifying the service associated to
            the event

        :type operation: str
        :param operation: A string identifying the operation of service
            associated to the event

        :type timestamp: int
        :param timestamp: Epoch time in milliseconds from when the HTTP request
            started

        :type latency: int
        :param latency: The time in milliseconds to complete the HTTP request
            whether it succeeded or failed

        :type url: str
        :param url: The URL the attempt was sent to

        :type http_status_code: int
        :param http_status_code: The HTTP status code of the HTTP response
            if there was a response

        :type request_headers: dict
        :param request_headers: The HTTP headers sent in making the HTTP
            request

        :type response_headers: dict
        :param response_headers: The HTTP headers returned in the HTTP response
            if there was a response

        :type parsed_error: dict
        :param parsed_error: The error parsed if the service returned an
            error back

        :type wire_exception: Exception
        :param wire_exception: The exception raised in sending the HTTP
            request (i.e. ConnectionError)
        r'   N)	r]   r   r=   r6   r>   r5   r?   rA   rB   )r	   r(   r)   r*   r=   r6   r>   r5   r?   rA   rB   r_   r   r   r      s    9  zAPICallAttemptEvent.__init__)NNNNNNN)r   r   r   r   rb   r   r   r_   r   r`      s          r`   c                   @   s&  e Zd ZdZdZdZdZdZddddZe	
d	e	
d
dZddddddddddddgZdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Zd<d= Zd>d? Z d@dA Z!dBdC Z"dDdE Z#dFdG Z$dHdI Z%dJS )KCSMSerializer         i   ZXAmznRequestIdZXAmzRequestIdZXAmzId2)zx-amzn-requestidzx-amz-request-idz
x-amz-id-2zSAWS4-HMAC-SHA256 Credential=(?P<access_key>\w+)/\d+/(?P<signing_region>[a-z0-9-]+)/zAWS (?P<access_key>\w+):)v4Zs3r(   r)   r*   r^   r=   rF   r6   r5   r>   r?   rA   rB   c                 C   s   |  | || _dS )zSerializes monitor events to CSM (Client Side Monitoring) format

        :type csm_client_id: str
        :param csm_client_id: The application identifier to associate
            to the serialized events
        N)_validate_client_idcsm_client_idr	   ri   r   r   r   r   d  s    
zCSMSerializer.__init__c                 C   s*   t || jkr&td| d| j dd S )Nz&The value provided for csm_client_id: z exceeds the maximum length of z characters)len_MAX_CLIENT_ID_LENGTH
ValueErrorrj   r   r   r   rh   n  s    z!CSMSerializer._validate_client_idc                 C   sf   |  |}| |}||d< | jD ]0}t||d}|dk	r"t| d| |||d q"ttj|ddS )zSerializes a monitor event to the CSM format

        :type event: BaseMonitorEvent
        :param event: The event to serialize to bytes

        :rtype: bytes
        :returns: The CSM serialized form of the event
        TypeNZ_serialize_)
event_type),:)
separators)_get_base_event_dict_get_event_type_SERIALIZEABLE_EVENT_PROPERTIESr$   r   jsondumps)r	   rR   
event_dictro   attrvaluer   r   r   	serializeu  s    	


  zCSMSerializer.serializec                 C   s   d| j dS )N   )VersionZClientId)ri   rQ   r   r   r   rs     s    z"CSMSerializer._get_base_event_dictc                 K   s   ||d< d S )NZServicer   )r	   r(   rx   r0   r   r   r   _serialize_service  s    z CSMSerializer._serialize_servicec                 K   s   ||d< d S )NZApir   )r	   r)   rx   r0   r   r   r   _serialize_operation  s    z"CSMSerializer._serialize_operationc                 K   s   ||d< d S )NZ	Timestampr   )r	   r*   rx   r0   r   r   r   _serialize_timestamp  s    z"CSMSerializer._serialize_timestampc                 K   s$   t ||d< |r | ||d  d S )NZAttemptCount)rk   _add_fields_from_last_attempt)r	   r^   rx   r0   r   r   r   _serialize_attempts  s    z!CSMSerializer._serialize_attemptsc                 C   s~   |j r2| |j }|d k	r"||d< | |j |d< |jd k	rF|j|d< |jd k	r`| |j|d |jd k	rz| |j|d d S )NRegion	UserAgentZFinalHttpStatusCodeApiCall)r5   _get_region_get_user_agentr>   rA   _serialize_parsed_errorrB   _serialize_wire_exception)r	   rx   last_attemptregionr   r   r   r     s*    


  
  z+CSMSerializer._add_fields_from_last_attemptc                 C   s&   |dkr||d< n|dkr"||d< d S )Nr   ZLatencyApiCallAttemptZAttemptLatencyr   )r	   r=   rx   ro   r   r   r   _serialize_latency  s    
z CSMSerializer._serialize_latencyc                 K   s   |rdnd|d< d S )Nr|   r   ZMaxRetriesExceededr   )r	   rF   rx   r0   r   r   r   _serialize_retries_exceeded  s    z)CSMSerializer._serialize_retries_exceededc                 K   s   t |j|d< d S )NZFqdn)r   netloc)r	   r6   rx   r0   r   r   r   _serialize_url  s    zCSMSerializer._serialize_urlc                 K   sX   |  ||d< | |r&| ||d< | |}|d k	r@||d< d|krT|d |d< d S )Nr   Z	AccessKeyr   zX-Amz-Security-TokenZSessionToken)r   
_is_signed_get_access_keyr   )r	   r5   rx   r0   r   r   r   r   _serialize_request_headers  s    

z(CSMSerializer._serialize_request_headersc                 K   s   ||d< d S )NZHttpStatusCoder   )r	   r>   rx   r0   r   r   r   _serialize_http_status_code  s    z)CSMSerializer._serialize_http_status_codec                 K   s,   | j  D ]\}}||kr
|| ||< q
d S rP   )"_RESPONSE_HEADERS_TO_EVENT_ENTRIESitems)r	   r?   rx   r0   headerentryr   r   r   _serialize_response_headers  s    z)CSMSerializer._serialize_response_headersc                 K   sH   |dkrdnd}|  |d | j||d < |  |d | j||d < d S )Nr   Final ZCodeZAwsExceptionMessageZAwsExceptionMessage)	_truncate_MAX_ERROR_CODE_LENGTH_MAX_MESSAGE_LENGTH)r	   rA   rx   ro   r0   field_prefixr   r   r   r     s      z%CSMSerializer._serialize_parsed_errorc                 K   sH   |dkrdnd}|  |jj| j||d < |  t|| j||d < d S )Nr   r   r   ZSdkExceptionZSdkExceptionMessage)r   rX   r   _MAX_EXCEPTION_CLASS_LENGTHstrr   )r	   rB   rx   ro   r0   r   r   r   r   r     s      z'CSMSerializer._serialize_wire_exceptionc                 C   s    t |trdS t |trdS d S )Nr   r   )rM   r,   r`   rQ   r   r   r   rt     s    

zCSMSerializer._get_event_typec                 C   s"   |  |}| |\}}|dS )NZ
access_key)_get_auth_value_get_auth_matchgroup)r	   r5   auth_valr#   
auth_matchr   r   r   r     s    
zCSMSerializer._get_access_keyc                 C   s<   |  |sd S | |}| |\}}|dkr2d S |dS )Nrg   Zsigning_region)r   r   r   r   )r	   r5   r   signature_versionr   r   r   r   r     s    

zCSMSerializer._get_regionc                 C   s   |  t|dd| jS )Nz
User-Agentr   )r   r   r@   _MAX_USER_AGENT_LENGTHr	   r5   r   r   r   r     s    zCSMSerializer._get_user_agentc                 C   s   d|kS NAuthorizationr   r   r   r   r   r   
  s    zCSMSerializer._is_signedc                 C   s   t |d S r   )r   r   r   r   r   r     s    zCSMSerializer._get_auth_valuec                 C   s2   | j  D ]"\}}||}|r
||f  S q
dS )N)NN)_AUTH_REGEXSr   match)r	   r   r   regexr   r   r   r   r     s
    
zCSMSerializer._get_auth_matchc                 C   s*   t ||kr&td|| |d | S |S )Nz6Truncating following value to maximum length of %s: %s)rk   r   r   )r	   text
max_lengthr   r   r   r     s    zCSMSerializer._truncateN)&r   r   r   rl   r   r   r   r   r   recompiler   ru   r   rh   r{   rs   r~   r   r   r   r   r   r   r   r   r   r   r   r   rt   r   r   r   r   r   r   r   r   r   r   r   rc   B  sh   	
	rc   c                   @   s    e Zd ZdZdd Zdd ZdS )SocketPublisheri    c                 C   s   || _ ||f| _|| _dS )a)  Publishes monitor events to a socket

        :type socket: socket.socket
        :param socket: The socket object to use to publish events

        :type host: string
        :param host: The host to send events to

        :type port: integer
        :param port: The port on the host to send events to

        :param serializer: The serializer to use to serialize the event
            to a form that can be published to the socket. This must
            have a `serialize()` method that accepts a monitor event
            and return bytes
        N)_socket_address_serializer)r	   sockethostport
serializerr   r   r   r   %  s    
zSocketPublisher.__init__c                 C   sF   | j |}t|| jkr2tdt|| j dS | j|| j dS )zPublishes a specified monitor event

        :type event: BaseMonitorEvent
        :param event: The monitor event to be sent
            over the publisher's socket to the desired address.
        z`Serialized event of size %s exceeds the maximum length allowed: %s. Not sending event to socket.N)	r   r{   rk   _MAX_MONITOR_EVENT_LENGTHr   r   r   sendtor   )r	   rR   Zserialized_eventr   r   r   r   :  s    zSocketPublisher.publishN)r   r   r   r   r   r   r   r   r   r   r   "  s   r   )rv   loggingr   r   Zbotocore.compatr   r   r   Zbotocore.retryhandlerr   rO   	getLoggerr   r   r   r   rU   r,   r`   rc   r   r   r   r   r   <module>   s   
,`<F a