a
    !f[                     @   s   d Z ddl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
 ejjZG dd deZG dd	 d	eZG d
d deZG dd deZdd ZdS )zTime series query for the `Google Stackdriver Monitoring API (V3)`_.

.. _Google Stackdriver Monitoring API (V3):
    https://cloud.google.com/monitoring/api/ref_v3/rest/v3/    projects.timeSeries/list
    N)_datetime_to_rfc3339_build_dataframe)
TimeSeriesc                   @   sD   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdS )Alignerz-Allowed values for the `supported aligners`_.
ALIGN_NONEALIGN_DELTA
ALIGN_RATEALIGN_INTERPOLATEALIGN_NEXT_OLDER	ALIGN_MIN	ALIGN_MAX
ALIGN_MEANALIGN_COUNT	ALIGN_SUMALIGN_STDDEVALIGN_COUNT_TRUEALIGN_FRACTION_TRUEN)__name__
__module____qualname____doc__r   r   r	   r
   r   r   r   r   r   r   r   r   r    r   r   X/var/www/html/python-backend/venv/lib/python3.9/site-packages/gcloud/monitoring/query.pyr   #   s   r   c                   @   sD   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdS )Reducerz-Allowed values for the `supported reducers`_.REDUCE_NONEREDUCE_MEAN
REDUCE_MIN
REDUCE_MAX
REDUCE_SUMREDUCE_STDDEVREDUCE_COUNTREDUCE_COUNT_TRUEREDUCE_FRACTION_TRUEREDUCE_PERCENTILE_99REDUCE_PERCENTILE_95REDUCE_PERCENTILE_50REDUCE_PERCENTILE_05N)r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r   r   r   r   r   5   s   r   c                   @   s   e Zd ZdZdZeddddfddZdd Zed	d
 Zedd Z	d&ddZ
dd Zdd Zdd Zdd Zd'ddZdd Zd(ddZd)ddZd*d d!Zd+d"d#Zd$d% ZdS ),Querya}  Query object for retrieving metric data.

    The preferred way to construct a query object is using the
    :meth:`~gcloud.monitoring.client.Client.query` method
    of the :class:`~gcloud.monitoring.client.Client` class.

    :type client: :class:`gcloud.monitoring.client.Client`
    :param client: The client to use.

    :type metric_type: string
    :param metric_type: The metric type name. The default value is
        :data:`Query.DEFAULT_METRIC_TYPE
        <gcloud.monitoring.query.Query.DEFAULT_METRIC_TYPE>`,
        but please note that this default value is provided only for
        demonstration purposes and is subject to change. See the
        `supported metrics`_.

    :type end_time: :class:`datetime.datetime` or None
    :param end_time: The end time (inclusive) of the time interval
        for which results should be returned, as a datetime object.
        The default is the start of the current minute.

        The start time (exclusive) is determined by combining the
        values of  ``days``, ``hours``, and ``minutes``, and
        subtracting the resulting duration from the end time.

        It is also allowed to omit the end time and duration here,
        in which case
        :meth:`~gcloud.monitoring.query.Query.select_interval`
        must be called before the query is executed.

    :type days: integer
    :param days: The number of days in the time interval.

    :type hours: integer
    :param hours: The number of hours in the time interval.

    :type minutes: integer
    :param minutes: The number of minutes in the time interval.

    :raises: :exc:`ValueError` if ``end_time`` is specified but
        ``days``, ``hours``, and ``minutes`` are all zero.
        If you really want to specify a point in time, use
        :meth:`~gcloud.monitoring.query.Query.select_interval`.

    .. _supported metrics: https://cloud.google.com/monitoring/api/metrics
    z/compute.googleapis.com/instance/cpu/utilizationNr   c                 C   s   d }|s|s|r>|d u r(t  jddd}|tj|||d }n|d urNtd|| _|| _|| _t|| _	d | _
d | _d | _d| _d S )Nr   )secondmicrosecond)dayshoursminutesz-Non-zero duration required for time interval.r   )_UTCNOWreplacedatetime	timedelta
ValueError_client	_end_time_start_time_Filter_filter_per_series_aligner_alignment_period_seconds_cross_series_reducer_group_by_fields)selfclientmetric_typeend_timer+   r,   r-   
start_timer   r   r   __init__z   s$    

zQuery.__init__c                 C   s   |   S N)iterr<   r   r   r   __iter__   s    zQuery.__iter__c                 C   s   | j jS )zThe metric type name.)r7   r>   rD   r   r   r   r>      s    zQuery.metric_typec                 C   s
   t | jS )zThe filter string.

        This is constructed from the metric type, the resource type, and
        selectors for the group ID, monitored projects, resource labels,
        and metric labels.
        )strr7   rD   r   r   r   filter   s    zQuery.filterc                 C   s   |   }||_||_|S )a  Copy the query and set the query time interval.

        Example::

            import datetime

            now = datetime.datetime.utcnow()
            query = query.select_interval(
                end_time=now,
                start_time=now - datetime.timedelta(minutes=5))

        As a convenience, you can alternatively specify the end time and
        an interval duration when you create the query initially.

        :type end_time: :class:`datetime.datetime`
        :param end_time: The end time (inclusive) of the time interval
            for which results should be returned, as a datetime object.

        :type start_time: :class:`datetime.datetime` or None
        :param start_time: The start time (exclusive) of the time interval
            for which results should be returned, as a datetime object.
            If not specified, the interval is a point in time.

        :rtype: :class:`Query`
        :returns: The new query object.
        )copyr4   r5   )r<   r?   r@   	new_queryr   r   r   select_interval   s    zQuery.select_intervalc                 C   s   |   }||j_|S )a  Copy the query and add filtering by group.

        Example::

            query = query.select_group('1234567')

        :type group_id: string
        :param group_id: The ID of a group to filter by.

        :rtype: :class:`Query`
        :returns: The new query object.
        )rH   r7   group_id)r<   rK   rI   r   r   r   select_group   s    zQuery.select_groupc                 G   s   |   }||j_|S )a  Copy the query and add filtering by monitored projects.

        This is only useful if the target project represents a Stackdriver
        account containing the specified monitored projects.

        Examples::

            query = query.select_projects('project-1')
            query = query.select_projects('project-1', 'project-2')

        :type args: tuple
        :param args: Project IDs limiting the resources to be included
            in the query.

        :rtype: :class:`Query`
        :returns: The new query object.
        )rH   r7   projects)r<   argsrI   r   r   r   select_projects   s    zQuery.select_projectsc                 O   s   |   }|jj|i | |S )a  Copy the query and add filtering by resource labels.

        Examples::

            query = query.select_resources(zone='us-central1-a')
            query = query.select_resources(zone_prefix='europe-')
            query = query.select_resources(resource_type='gce_instance')

        A keyword argument ``<label>=<value>`` ordinarily generates a filter
        expression of the form::

            resource.label.<label> = "<value>"

        However, by adding ``"_prefix"`` or ``"_suffix"`` to the keyword,
        you can specify a partial match.

        ``<label>_prefix=<value>`` generates::

            resource.label.<label> = starts_with("<value>")

        ``<label>_suffix=<value>`` generates::

            resource.label.<label> = ends_with("<value>")

        As a special case, ``"resource_type"`` is treated as a special
        pseudo-label corresponding to the filter object ``resource.type``.
        For example, ``resource_type=<value>`` generates::

            resource.type = "<value>"

        See the `defined resource types`_.

        .. note::

            The label ``"instance_name"`` is a metric label,
            not a resource label. You would filter on it using
            ``select_metrics(instance_name=...)``.

        :type args: tuple
        :param args: Raw filter expression strings to include in the
            conjunction. If just one is provided and no keyword arguments
            are provided, it can be a disjunction.

        :type kwargs: dict
        :param kwargs: Label filters to include in the conjunction as
            described above.

        :rtype: :class:`Query`
        :returns: The new query object.

        .. _defined resource types:
            https://cloud.google.com/monitoring/api/v3/monitored-resources
        )rH   r7   select_resourcesr<   rN   kwargsrI   r   r   r   rP      s    6zQuery.select_resourcesc                 O   s   |   }|jj|i | |S )aj  Copy the query and add filtering by metric labels.

        Examples::

            query = query.select_metrics(instance_name='myinstance')
            query = query.select_metrics(instance_name_prefix='mycluster-')

        A keyword argument ``<label>=<value>`` ordinarily generates a filter
        expression of the form::

            metric.label.<label> = "<value>"

        However, by adding ``"_prefix"`` or ``"_suffix"`` to the keyword,
        you can specify a partial match.

        ``<label>_prefix=<value>`` generates::

            metric.label.<label> = starts_with("<value>")

        ``<label>_suffix=<value>`` generates::

            metric.label.<label> = ends_with("<value>")

        :type args: tuple
        :param args: Raw filter expression strings to include in the
            conjunction. If just one is provided and no keyword arguments
            are provided, it can be a disjunction.

        :type kwargs: dict
        :param kwargs: Label filters to include in the conjunction as
            described above.

        :rtype: :class:`Query`
        :returns: The new query object.
        )rH   r7   select_metricsrQ   r   r   r   rS   $  s    $zQuery.select_metricsc                 C   s(   |   }||_|d|d|    |_|S )a  Copy the query and add temporal alignment.

        If ``per_series_aligner`` is not :data:`Aligner.ALIGN_NONE`, each time
        series will contain data points only on the period boundaries.

        Example::

            query = query.align(Aligner.ALIGN_MEAN, minutes=5)

        It is also possible to specify the aligner as a literal string::

            query = query.align('ALIGN_MEAN', minutes=5)

        :type per_series_aligner: string
        :param per_series_aligner: The approach to be used to align
            individual time series. For example: :data:`Aligner.ALIGN_MEAN`.
            See :class:`Aligner` and the descriptions of the `supported
            aligners`_.

        :type seconds: integer
        :param seconds: The number of seconds in the alignment period.

        :type minutes: integer
        :param minutes: The number of minutes in the alignment period.

        :type hours: integer
        :param hours: The number of hours in the alignment period.

        :rtype: :class:`Query`
        :returns: The new query object.

        .. _supported aligners:
            https://cloud.google.com/monitoring/api/ref_v3/rest/v3/            projects.timeSeries/list#Aligner
        <   )rH   r8   r9   )r<   Zper_series_alignersecondsr-   r,   rI   r   r   r   alignL  s    $
zQuery.alignc                 G   s   |   }||_||_|S )a  Copy the query and add cross-series reduction.

        Cross-series reduction combines time series by aggregating their
        data points.

        For example, you could request an aggregated time series for each
        combination of project and zone as follows::

            query = query.reduce(Reducer.REDUCE_MEAN,
                                 'resource.project_id', 'resource.zone')

        :type cross_series_reducer: string
        :param cross_series_reducer:
            The approach to be used to combine time series. For example:
            :data:`Reducer.REDUCE_MEAN`. See :class:`Reducer` and the
            descriptions of the `supported reducers`_.

        :type group_by_fields: strings
        :param group_by_fields:
            Fields to be preserved by the reduction. For example, specifying
            just ``"resource.zone"`` will result in one time series per zone.
            The default is to aggregate all of the time series into just one.

        :rtype: :class:`Query`
        :returns: The new query object.

        .. _supported reducers:
            https://cloud.google.com/monitoring/api/ref_v3/rest/v3/            projects.timeSeries/list#Reducer
        )rH   r:   r;   )r<   Zcross_series_reducerZgroup_by_fieldsrI   r   r   r   reducev  s    zQuery.reduceFc                 c   sV   t | ||dd D ]8\}}tt jdd |D }|  |j|dV  qdS )a  Yield all time series objects selected by the query.

        The generator returned iterates over
        :class:`~gcloud.monitoring.timeseries.TimeSeries` objects
        containing points ordered from oldest to newest.

        Note that the :class:`Query` object itself is an iterable, such that
        the following are equivalent::

            for timeseries in query:
                ...

            for timeseries in query.iter():
                ...

        :type headers_only: boolean
        :param headers_only:
             Whether to omit the point data from the time series objects.

        :type page_size: integer or None
        :param page_size:
            An optional positive number specifying the maximum number of
            points to return per page. This can be used to control how far
            the iterator reads ahead.

        :raises: :exc:`ValueError` if the query time interval has not been
            specified.
        c                 S   s   |   S rB   )header)fragmentr   r   r   <lambda>      zQuery.iter.<locals>.<lambda>c                 s   s   | ]}|j V  qd S rB   points).0rY   r   r   r   	<genexpr>  s   zQuery.iter.<locals>.<genexpr>r\   N)	itertoolsgroupby_iter_fragmentslistchainfrom_iterablereverserX   )r<   headers_only	page_sizeZ
timeseries	fragmentsr]   r   r   r   rC     s    

z
Query.iterc                 c   s   | j du rtddj| jjd}d}t| j|||d}| jjjd||d}|	dd	D ]}t
|V  qZ|	d
}|s&q~q&dS )zYield all time series fragments selected by the query.

        There may be multiple fragments per time series. These will be
        contiguous.

        The parameters and return value are as for :meth:`Query.iter`.
        Nz"Query time interval not specified.z/projects/{project}/timeSeries/project)rg   rh   
page_tokenGET)methodpathZquery_paramsZ
timeSeriesr   ZnextPageToken)r4   r2   formatr3   rk   rc   _build_query_params
connectionZapi_requestgetr   
_from_dict)r<   rg   rh   ro   rl   paramsresponseinfor   r   r   rb     s*    

zQuery._iter_fragmentsc                 c   s   d| j fV  dt| jddfV  | jdur>dt| jddfV  | jdurTd| jfV  | jdurvdj| jd	}d
|fV  | jdurd| jfV  | jD ]}d|fV  q|rdV  |durd|fV  |durd|fV  dS )ag  Yield key-value pairs for the URL query string.

        We use a series of key-value pairs (suitable for passing to
        ``urlencode``) instead of a ``dict`` to allow for repeated fields.

        :type headers_only: boolean
        :param headers_only:
             Whether to omit the point data from the
             :class:`~gcloud.monitoring.timeseries.TimeSeries` objects.

        :type page_size: integer or None
        :param page_size: A limit on the number of points to return per page.

        :type page_token: string or None
        :param page_token: A token to continue the retrieval.
        rG   zinterval.endTimeF)Zignore_zoneNzinterval.startTimezaggregation.perSeriesAlignerz	{period}s)Zperiodzaggregation.alignmentPeriodzaggregation.crossSeriesReducerzaggregation.groupByFields)viewHEADERSZpageSizeZ	pageToken)	rG   r   r4   r5   r8   r9   rp   r:   r;   )r<   rg   rh   rl   Zalignment_periodfieldr   r   r   rq     s6    








zQuery._build_query_paramsc                 C   s   t | ||S )a  Return all the selected time series as a :mod:`pandas` dataframe.

        .. note::

            Use of this method requires that you have :mod:`pandas` installed.

        Examples::

            # Generate a dataframe with a multi-level column header including
            # the resource type and all available resource and metric labels.
            # This can be useful for seeing what labels are available.
            dataframe = query.as_dataframe()

            # Generate a dataframe using a particular label for the column
            # names.
            dataframe = query.as_dataframe(label='instance_name')

            # Generate a dataframe with a multi-level column header.
            dataframe = query.as_dataframe(labels=['zone', 'instance_name'])

            # Generate a dataframe with a multi-level column header, assuming
            # the metric is issued by more than one type of resource.
            dataframe = query.as_dataframe(
                labels=['resource_type', 'instance_id'])

        :type label: string or None
        :param label: The label name to use for the dataframe header.
            This can be the name of a resource label or metric label
            (e.g., ``"instance_name"``), or the string ``"resource_type"``.

        :type labels: list of strings, or None
        :param labels: A list or tuple of label names to use for the dataframe
            header. If more than one label name is provided, the resulting
            dataframe will have a multi-level column header. Providing values
            for both ``label`` and ``labels`` is an error.

        :rtype: :class:`pandas.DataFrame`
        :returns: A dataframe where each column represents one time series.
        r   )r<   labellabelsr   r   r   as_dataframe  s    (zQuery.as_dataframec                 C   s   t  | }t  | j|_|S )zgCopy the query object.

        :rtype: :class:`Query`
        :returns: The new query object.
        )rH   r7   )r<   rI   r   r   r   rH   ?  s    
z
Query.copy)N)r   r   r   )FN)FN)FNN)NN)r   r   r   r   ZDEFAULT_METRIC_TYPErA   rE   propertyr>   rG   rJ   rL   rO   rP   rS   rV   rW   rC   rb   rq   r}   rH   r   r   r   r   r(   G   s0   0


	
 :(
*$
'
!  
3
*r(   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )r6   z&Helper for assembling a filter string.c                 C   s"   || _ d | _d| _d | _d | _d S )Nr   )r>   rK   rM   resource_label_filtermetric_label_filter)r<   r>   r   r   r   rA   O  s
    z_Filter.__init__c                 O   s   t dg|R i || _dS )zPSelect by resource labels.

        See :meth:`Query.select_resources`.
        resourceN)_build_label_filterr   r<   rN   rR   r   r   r   rP   V  s
    z_Filter.select_resourcesc                 O   s   t dg|R i || _dS )zLSelect by metric labels.

        See :meth:`Query.select_metrics`.
        ZmetricN)r   r   r   r   r   r   rS   ^  s
    z_Filter.select_metricsc                 C   s~   dj | jdg}| jd ur.|dj | jd | jrP|ddd | jD  | jrb|| j | jrt|| j d|S )	Nzmetric.type = "{type}")typezgroup.id = "{id}")idz OR c                 s   s   | ]}d j |dV  qdS )zproject = "{project}"rj   N)rp   )r^   rk   r   r   r   r_   l  s   z"_Filter.__str__.<locals>.<genexpr> AND )rp   r>   rK   appendrM   joinr   r   )r<   filtersr   r   r   __str__f  s    

z_Filter.__str__N)r   r   r   r   rA   rP   rS   r   r   r   r   r   r6   L  s
   r6   c                 O   s   t |}t|D ]\}}|du r$qd}|ds<|drL|dd\}}| dkrb|dkrbd}nd	| d
|f}|dkrd}n|dkrd}nd}||j||d qdt|S )zAConstruct a filter string to filter on metric or resource labels.N_prefixZ_suffix_   r   Zresource_typezresource.type.r{   prefixz{key} = starts_with("{value}")suffixz{key} = ends_with("{value}")z{key} = "{value}")keyvaluer   )	rc   six	iteritemsendswithrsplitr   r   rp   sorted)categoryrN   rR   Ztermsr   r   r   termr   r   r   r   x  s"    r   )r   rH   r0   r`   r   Zgcloud._helpersr   Zgcloud.monitoring._dataframer   Zgcloud.monitoring.timeseriesr   utcnowr.   objectr   r   r(   r6   r   r   r   r   r   <module>   s"       	,