
    9YfJ                        d Z ddlZddlZddlZddlmZ ddlmZ ddlmZ 	 ddlm	Z	 ddlmZ ddlmZ dd	lmZ dd
lmZmZmZmZmZmZmZ ddlmZ  ej6                  d      ZddddZ G d de      Zy# e
$ r	 ddlmZ	 Y [w xY w)a  
ThreadStats is a tool for collecting application metrics without hindering
performance. It collects metrics in the application thread with very little overhead
and allows flushing metrics in process, in a thread or in a greenlet, depending
on your application's needs.
    N)contextmanagerwraps)time)	monotonic)ApiNotInitialized)
MetricType)EventsAggregator)MetricsAggregatorCounterGauge	HistogramTimingDistributionSet)HttpReporterzdatadog.threadstatsenvserviceversion)DD_ENV
DD_SERVICE
DD_VERSIONc                       e Zd ZddZ	 	 	 	 	 	 ddZ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edd       ZddZddZddZd Zd Zd Zy)ThreadStatsNc                    || _         t        j                  j                  dd      j	                  d      D cg c]  }|s|	 }}t
        j                         D ]J  \  }}t        j                  j                  |d      }|s)|j                  dj                  ||             L |g }||z   | _	        d| _
        || _        yc c}w )aL  
        Initialize a threadstats object.

        :param namespace: Namespace to prefix all metric names
        :type namespace: string

        :param constant_tags: Tags to attach to every metric reported by this client
        :type constant_tags: list of strings

        :param compress_payload: compress the payload using zlib
        :type compress_payload: bool

        :envvar DATADOG_TAGS: Tags to attach to every metric reported by ThreadStats client
        :type DATADOG_TAGS: comma-delimited string

        :envvar DD_ENV: the env of the service running the ThreadStats client.
        If set, it is appended to the constant (global) tags of the client.
        :type DD_ENV: string

        :envvar DD_SERVICE: the name of the service running the ThreadStats client.
        If set, it is appended to the constant (global) tags of the client.
        :type DD_SERVICE: string

        :envvar DD_VERSION: the version of the service running the ThreadStats client.
        If set, it is appended to the constant (global) tags of the client.
        :type DD_VERSION: string
        DATADOG_TAGS ,z{name}:{value})namevalueNT)	namespaceosenvirongetsplitDD_ENV_TAGS_MAPPINGitemsappendformatconstant_tags	_disabledcompress_payload)	selfr!   r*   r,   tagenv_tagsvartag_namer    s	            X/var/www/highfloat_scraper/venv/lib/python3.12/site-packages/datadog/threadstats/base.py__init__zThreadStats.__init__*   s    : ##%::>>."#E#K#KC#PXCTWCXX0668 	UMCJJNN3+E 0 7 7XU 7 ST	U  M*X5  0 Ys   CCc                     | _         | _        | _        | _        d _        t         j                         _        t                _        t         j                         _        d _        d _         j                  rt        j                  d       n%|r j!                          n|r j#                          t%        j&                   fd       y)a  
        Start the ThreadStats instance with the specified metric flushing method and preferences.

        By default, metrics will be flushed in a thread.

        >>> stats.start()

        If you're running a gevent server and want to flush metrics in a
        greenlet, set *flush_in_greenlet* to True. Be sure to import and monkey
        patch gevent before starting ThreadStats. ::

        >>> from gevent import monkey; monkey.patch_all()
        >>> stats.start(flush_in_greenlet=True)

        If you'd like to flush metrics in process, set *flush_in_thread*
        to False, though you'll have to call ``flush`` manually to post metrics
        to the server. ::

        >>> stats.start(flush_in_thread=False)

        If for whatever reason, you need to disable metrics collection in a
        hurry, set ``disabled`` to True and metrics won't be collected or flushed.

        >>> stats.start(disabled=True)

        *Note:* Please remember to set your API key before,
            using datadog module ``initialize`` method.

        >>> from datadog import initialize, ThreadStats
        >>> initialize(api_key="my_api_key")
        >>> stats = ThreadStats()
        >>> stats.start()
        >>> stats.increment("home.page.hits")

        :param flush_interval: The number of seconds to wait between flushes.
        :type flush_interval: int
        :param flush_in_thread: True if you'd like to spawn a thread to flush metrics.
            It will run every `flush_interval` seconds.
        :type flush_in_thread: bool
        :param flush_in_greenlet: Set to true if you'd like to flush in a gevent greenlet.
        :type flush_in_greenlet: bool
        :param disabled: Disable metrics collection
        :type disabled: bool
        F)r,   r   z8ThreadStats instance is disabled. No metrics will flush.c                  8     j                  t        d            S )Ninf)flushfloatr-   s   r2   <lambda>z#ThreadStats.start.<locals>.<lambda>   s    

5< 8     N)flush_intervalroll_up_intervaldevicer+   _is_auto_flushingr   _metric_aggregatorr
   _event_aggregatorr   r,   reporter_is_flush_in_progressflush_countloginfo_start_flush_greenlet_start_flush_threadatexitregister)r-   r<   r=   r>   flush_in_threadflush_in_greenletdisableds   `      r2   startzThreadStats.startU   s    j - 0!!& #4D4I4I"J!1!3
 %d6K6KL%*">>HHOP **, ((* 	89r;   c                 z    | j                   sy| j                  r"| j                  j                          d| _         yy )NTF)r?   _flush_threadendr9   s    r2   stopzThreadStats.stop   s9    %%""$%*D" r;   c
                     | j                   sQ|}
| j                  r|r|| j                  z   }
n| j                  }
| j                  j                  ||||||||
|		       yy)a  
        Send an event. See http://docs.datadoghq.com/api/ for more info.

        >>> stats.event("Man down!", "This server needs assistance.")
        >>> stats.event("The web server restarted",             "The web server is up again", alert_type="success")
        )	titletext
alert_typeaggregation_keysource_type_namedate_happenedprioritytagshostN)r+   r*   rA   	add_event)r-   rT   messagerV   rW   rX   rY   rZ   r[   hostname
event_tagss              r2   eventzThreadStats.event   sp    & ~~J!!!%(:(:!:J!%!3!3J"",,% /!1+! - 
 r;   c           	          | j                   s3| j                  j                  |||xs
 t               |t        ||       yy)a  
        Record the current ``value`` of a metric. The most recent value in
        a given flush interval will be recorded. Optionally, specify a set of
        tags to associate with the metric. This should be used for sum values
        such as total hard disk space, process uptime, total number of active
        users, or number of rows in a database table.

        >>> stats.gauge("process.uptime", time.time() - process_start_time)
        >>> stats.gauge("cache.bytes.free", cache.get_free_bytes(), tags=["version:1.0"])
        sample_rater\   N)r+   r@   	add_pointr   r   r-   metric_namer    	timestampr[   rd   r\   s          r2   gaugezThreadStats.gauge   sA     ~~##--T9#6uR]dh .  r;   c           	          | j                   s3| j                  j                  |||xs
 t               |t        ||       yy)a  
        Add ``value`` to the current set. The length of the set is
        flushed as a gauge to Datadog. Optionally, specify a set of
        tags to associate with the metric.

        >>> stats.set("example_metric.set", "value_1", tags=["environment:dev"])
        rc   N)r+   r@   re   r   r   rf   s          r2   setzThreadStats.set   sA     ~~##--T9#6sP[bf .  r;   c           	          | j                   s3| j                  j                  |||xs
 t               |t        ||       yy)a`  
        Increment the counter by the given ``value``. Optionally, specify a list of
        ``tags`` to associate with the metric. This is useful for counting things
        such as incrementing a counter each time a page is requested.

        >>> stats.increment('home.page.hits')
        >>> stats.increment('bytes.processed', file.size())
        rc   Nr+   r@   re   r   r   rf   s          r2   	incrementzThreadStats.increment   sA     ~~##--T9#6wT_fj .  r;   c           	          | j                   s4| j                  j                  |||xs
 t               | t        ||       yy)z
        Decrement a counter, optionally setting a value, tags and a sample
        rate.

        >>> stats.decrement("files.remaining")
        >>> stats.decrement("active.connections", 2)
        rc   Nrm   rf   s          r2   	decrementzThreadStats.decrement  sC     ~~##--T9#6U`gk .  r;   c           	          | j                   s3| j                  j                  |||xs
 t               |t        ||       yy)au  
        Sample a histogram value. Histograms will produce metrics that
        describe the distribution of the recorded values, namely the maximum, minimum,
        average, count and the 75/85/95/99 percentiles. Optionally, specify
        a list of ``tags`` to associate with the metric.

        >>> stats.histogram("uploaded_file.size", uploaded_file.size())
        rc   N)r+   r@   re   r   r   rf   s          r2   	histogramzThreadStats.histogram  sA     ~~##--T9#6yVahl .  r;   c           	          | j                   s3| j                  j                  |||xs
 t               |t        ||       yy)a  
        Sample a distribution value. Distributions will produce metrics that
        describe the distribution of the recorded values, namely the maximum,
        median, average, count and the 50/75/90/95/99 percentiles. Optionally,
        specify a list of ``tags`` to associate with the metric.

        >>> stats.distribution("uploaded_file.size", uploaded_file.size())
        rc   N)r+   r@   re   r   r   rf   s          r2   distributionzThreadStats.distribution  sA     ~~##--T9#6|Ydko .  r;   c           	          | j                   s3| j                  j                  |||xs
 t               |t        ||       yy)z
        Record a timing, optionally setting tags and a sample rate.

        >>> stats.timing("query.response.time", 1234)
        rc   N)r+   r@   re   r   r   rf   s          r2   timingzThreadStats.timing*  sA     ~~##--T9#6vS^ei .  r;   c           
   #      K   t               }	 d t               }| j                  |||z
  t               |||       y# t               }| j                  |||z
  t               |||       w xY ww)a  
        A context manager that will track the distribution of the contained code's run time.
        Optionally specify a list of tags to associate with the metric.
        ::

            def get_user(user_id):
                with stats.timer("user.query.time"):
                    # Do what you need to ...
                    pass

            # Is equivalent to ...
            def get_user(user_id):
                start = time.time()
                try:
                    # Do what you need to ...
                    pass
                finally:
                    stats.histogram("user.query.time", time.time() - start)
        N)r[   rd   r\   )r   rv   r   )r-   rg   rd   r[   r\   rN   rQ   s          r2   timerzThreadStats.timer5  si     * 	i+CKKS5[$&tQ\cgKh +CKKS5[$&tQ\cgKhs   A0? -A0.A--A0c                 "      fd}|S )a  
        A decorator that will track the distribution of a function's run time.
        Optionally specify a list of tags to associate with the metric.
        ::

            @stats.timed("user.query.time")
            def get_user(user_id):
                # Do what you need to ...
                pass

            # Is equivalent to ...
            start = time.time()
            try:
                get_user(user_id)
            finally:
                stats.histogram("user.query.time", time.time() - start)
        c                 :     t                fd       }|S )Nc                  l    j                        5   | i |}|cd d d        S # 1 sw Y   y xY wN)rx   )	argskwargsresultfuncr\   rg   rd   r-   r[   s	      r2   wrappedz3ThreadStats.timed.<locals>.wrapper.<locals>.wrappede  s<    ZZ[$E "!4262F!" " "s   
*3r   )r   r   r\   rg   rd   r-   r[   s   ` r2   wrapperz"ThreadStats.timed.<locals>.wrapperd  s%    4[" " "
 Nr;    )r-   rg   rd   r[   r\   r   s   ````` r2   timedzThreadStats.timedQ  s    &	 	 r;   c                    	 | j                   rt        j                  d       	 d| _         y| j                  rt        j	                  d       	 d| _         yd| _         | j                  |xs
 t                     \  }}t        |      }|rW| xj                  dz  c_        t        j                  d| j                  d|d       | j                  j                  |       nt        j                  d	       t        |      }|rW| xj                  dz  c_        t        j                  d| j                  d|d
       | j                  j                  |       nt        j                  d       | j                         }t        |      }|rW| xj                  dz  c_        t        j                  d| j                  d|d       | j                  j                  |       nt        j                  d       d| _         y# t        $ r  t        $ r) 	 t        j!                  d       n# t        $ r Y nw xY wY Bw xY w# d| _         w xY w)z
        Flush and post all metrics to the server. Note that this is a blocking
        call, so it is likely not suitable for user facing processes. In those
        cases, it's probably best to flush in a thread or greenlet.
        z2A flush is already in progress. Skipping this one.Fz$Not flushing because we're disabled.T   zFlush #z	 sending z metricsz No metrics to flush. Continuing.z distributionsz&No distributions to flush. Continuing.z eventszNo events to flush. Continuing.z!Error flushing metrics and eventsN)rC   rE   debugr+   rF    _get_aggregate_metrics_and_distsr   lenrD   rB   flush_metricsflush_distributions_get_aggregate_eventsflush_eventsr   	Exception	exception)r-   rh   metricsdistscount_metricscount_distseventscount_eventss           r2   r7   zThreadStats.flusho  s   -	/))		NOT */D&S ~~?@N */D&K *.D& "BB9CVPTPVWNGULM  A% 		D<L<Lm\]++G4		<=e*K  A% 		$BRBRT_`a11%8		BC //1Fv;L  A% 		4;K;K\Z[**62		;< */D& ! 	 	AB 	 */D&sS   !H  !H  F"H   H;H)(H;)	H52H;4H55H;8H> :H;;H> >	Ic           	         | j                   j                  |      }g }g }|D ]  \  }}}}}	}
}|}|}| j                  r|r|| j                  z   }n| j                  }| j                  r| j                  dz   |z   }|||gg|
|	| j                  ||d}|
t
        j                  k(  r|j                  |       |j                  |        ||fS )zS
        Get, format and return the rolled up metrics from the aggregator.
        .)metricpointstyper\   r>   r[   interval)r@   r7   r*   r!   r>   r	   r   r(   )r-   
flush_timerolled_up_metricsr   r   rh   r    r   r[   r\   metric_typer   metric_tagsrg   r   s                  r2   r   z,ThreadStats._get_aggregate_metrics_and_dists  s    
 !3399*E IZ 	'EIudD$XKK !!"&););";K"&"4"4K ~~"nns2T9 &%u-.#++#$F j555V$v&7	'8 r;   c                 :    | j                   j                         }|S r|   )rA   r7   )r-   r   s     r2   r   z!ThreadStats._get_aggregate_events  s    ''--/r;   c                     ddl m}  j                  rt        j	                  d       yd _         fd}t        j	                  d j
                  z          | j
                  |       _         j                  j                          y)z" Start a thread to flush metrics. r   )PeriodicTimerAutoflushing already started.NTc                      	 t         j                  d        j                          y # t        $ r) 	 t         j	                  d       Y y # t        $ r Y Y y w xY ww xY w)NzFlushing metrics in threadzError flushing in thread)rE   r   r7   r   r   r9   s   r2   r7   z.ThreadStats._start_flush_thread.<locals>.flush  sQ    		67

 MM"<=  s&   %) 	AA

	AAAAz'Starting flush thread with interval %s.)"datadog.threadstats.periodic_timerr   r?   rE   rF   r<   rP   rN   )r-   r   r7   s   `  r2   rH   zThreadStats._start_flush_thread  sm    D!!HH45!%	 	:T=P=PPQ*4+>+>F  "r;   c                       j                   rt        j                  d       y d _         dd l fd}t        j                  d j                  z         j                  |       y )Nr   Tr   c                      	 	 t         j                  d       j                           j                  j                         B# t
        $ r) 	 t         j                  d       n# t
        $ r Y nw xY wY 2w xY w)NzFlushing metrics in greenletzError flushing in greenlet)rE   r   r7   sleepr<   r   r   )geventr-   s   r2   r7   z0ThreadStats._start_flush_greenlet.<locals>.flush  sm    II<=JJLLL!4!45	 
 ! &BC$ s6   A A 	A7A%$A7%	A1.A70A11A76A7z)Starting flush greenlet with interval %s.)r?   rE   rF   r   r<   spawn)r-   r7   r   s   ` @r2   rG   z!ThreadStats._start_flush_greenlet  sR    !!HH45!%
	 	<t?R?RRSUr;   )r   NF)
   r   NTFF)NNNNNNN)NNr   N)r   NNr   N)r   NNr|   )__name__
__module____qualname__r3   rN   rR   ra   ri   rk   rn   rp   rr   rt   rv   r   rx   r   r7   r   r   rH   rG   r   r;   r2   r   r   )   s    )1Z O:b &P 	 i i6<3/j& P
#0r;   r   ) __doc__rI   loggingr"   
contextlibr   	functoolsr   r   r   ImportErrordatadog.api.exceptionsr   datadog.threadstats.constantsr	   datadog.threadstats.eventsr
   datadog.threadstats.metricsr   r   r   r   r   r   r   datadog.threadstats.reportersr   	getLoggerrE   r&   objectr   r   r;   r2   <module>r      s      	 &  '
 5 4 7 o o o 6 g-.  V& V)  '&'s   A6 6BB