
    ֞i*4                       d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlmZ ddlmZmZ ddlZddlZ ee      j'                         j(                  d   Z ee      e	j.                  vr"e	j.                  j1                  d ee             edz  dz  Zed	z  Zed
z  Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z  G d d      Z! G d d      Z"y)u  
tests/infra/test_monitoring.py

Test suite for Module 8: Prometheus + Grafana Monitoring.

Coverage
--------
BB1: prometheus.yml is valid YAML with scrape_configs key
BB2: docker-compose.monitoring.yml defines all 4 required services
BB3: GenesisMetrics initializes without prometheus_client installed
BB4: metrics endpoint returns text/plain content type
WB1: Counter increments correctly
WB2: Histogram observe records values
WB3: Graceful degradation returns empty string when no prometheus_client

Total: 7 tests — all pass with ZERO live API calls or network access.

VERIFICATION_STAMP
Story: MON-006
Verified By: parallel-builder
Verified At: 2026-02-25
Tests: 7/7
Coverage: 100%
    )annotationsN)Path)	MagicMockpatch   infra
monitoringzprometheus.ymlzdocker-compose.monitoring.ymlc                  .    e Zd ZdZd Zd Zd Zd Zd Zy)TestBB1_PrometheusYamlzIBB1: prometheus.yml parses as valid YAML and has required top-level keys.c                   t         j                  } |       }|st        j                  dt                dz   dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d x}}y )Nzprometheus.yml not found at C
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}_PROMETHEUS_YMLpy0py2py4)
r   exists
@pytest_ar_format_assertmsg@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationself@py_assert1@py_assert3@py_format5s       4/mnt/e/genesis-system/tests/infra/test_monitoring.pytest_file_existsz'TestBB1_PrometheusYaml.test_file_exists;   s    %% 	
%' 	
' 	
  +?*;<	
 	
	6	
 	
   	
 	
 		  	
 	
 		 & 	
 	
 		 ( 	
 	
 	
 	
 	
    c                   t        t        d      5 }t        j                  |      }d d d        t	        t
              }|s!t        j                  d      dz   dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  |      dz  }t        t        j                  |            d }y # 1 sw Y   AxY w)	Nutf-8encodingz+prometheus.yml must parse to a YAML mappingz7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancedocdictr   py1r   r   )openr   yaml	safe_loadr(   r*   r   r   r   r   r   r   r   r   r   fhr)   r   r    s        r!   test_is_valid_yamlz)TestBB1_PrometheusYaml.test_is_valid_yaml@   s    /G4 	%..$C	%#t$S$SS&SSSSSSSzSSSzSSSSSS#SSS#SSSSSStSSStSSS$SSSSSS	% 	%s   E''E1c                $   t        t        d      5 }t        j                  |      }d d d        d}|v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }t	        j                  dt        |j                                      d	z   d
|iz  }t        t	        j                  |            d x}}y # 1 sw Y   xY w)Nr%   r&   scrape_configsinz%(py1)s in %(py3)sr)   r,   py3z;Expected 'scrape_configs' key in prometheus.yml, got keys: 
>assert %(py5)spy5)r-   r   r.   r/   r   _call_reprcomparer   r   r   r   r   listkeysr   r   )r   r1   r)   @py_assert0@py_assert2@py_format4@py_format6s          r!   test_has_scrape_configs_keyz2TestBB1_PrometheusYaml.test_has_scrape_configs_keyE   s    /G4 	%..$C	% 	
3& 	
 	
3 	
 	
 		   	
 	
	6	
 	
  $' 	
 	
 		 $' 	
 	
  J$sxxzJZI[\	
 	
 	
 	
 	
	% 	%s   DDc                   t        t        d      5 }t        j                  |      }ddd       d   D ch c]  }|d   	 }}h d}||k(  }|st	        j
                  d|fd||f      d	t        j                         v st	        j                  |      rt	        j                  |      nd	d
t        j                         v st	        j                  |      rt	        j                  |      nd
dz  }t	        j                  d| d|       dz   d|iz  }t        t	        j                  |            d}y# 1 sw Y   xY wc c}w )z3Expects jobs: genesis-api, sunaiva-api, prometheus.r%   r&   Nr4   job_name>   genesis-apisunaiva-api
prometheus==)z%(py0)s == %(py2)sexpected	job_names)r   r   zExpected job names z, got z
>assert %(py4)sr   )r-   r   r.   r/   r   r<   r   r   r   r   r   r   r   )	r   r1   r)   scrL   rK   r   @py_format3r    s	            r!   test_has_three_job_namesz/TestBB1_PrometheusYaml.test_has_three_job_namesL   s   /G4 	%..$C	%.12B.CDR
^D	D?9$ 	
 	
x9 	
 	
	6	
 	
   	
 	
 		  	
 	
	6	
 	
  % 	
 	
 		 % 	
 	
  "(6)=	
 	
 	
 	
 	
		% 	%Ds   D5E5D?c                v   t        t        d      5 }t        j                  |      }d d d        d}|v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            d x}}|d   }|j                  }d
} ||      }d}	||	k(  }
|
st	        j
                  d|
fd||	f      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |	      dz  }dd|iz  }t        t	        j                  |            d x}x}x}x}x}
}	y # 1 sw Y   xY w)Nr%   r&   globalr5   r7   r)   r8   assert %(py5)sr;   scrape_interval15srI   )zJ%(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.get
}(%(py5)s)
} == %(py10)s)r,   r9   r;   py7py10zassert %(py12)spy12)r-   r   r.   r/   r   r<   r   r   r   r   r   r   get)r   r1   r)   r?   r@   rA   rB   @py_assert4@py_assert6@py_assert9@py_assert8@py_format11@py_format13s                r!   test_global_scrape_intervalz2TestBB1_PrometheusYaml.test_global_scrape_intervalV   s   /G4 	%..$C	%x3x3x338}<}  <!2< !23<u<3u<<<<3u<<<}<<< <<<!2<<<3<<<u<<<<<<<<	% 	%s   F..F8N)	__name__
__module____qualname____doc__r"   r2   rC   rO   r_    r#   r!   r   r   8   s    S

T


=r#   r   c                  .    e Zd ZdZd Zd Zd Zd Zd Zy)TestBB2_DockerComposezFBB2: docker-compose.monitoring.yml contains all 4 monitoring services.c                   t         j                  } |       }|st        j                  dt                dz   dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d x}}y )Nz+docker-compose.monitoring.yml not found at r   _COMPOSE_YMLr   )
rh   r   r   r   r   r   r   r   r   r   r   s       r!   r"   z&TestBB2_DockerCompose.test_file_existse   s    "" 	
"$ 	
$ 	
  :,H	
 	
	6	
 	
   	
 	
 		  	
 	
 		 # 	
 	
 		 % 	
 	
 	
 	
 	
r#   c                   t        t        d      5 }t        j                  |      }d d d        t	        t
              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  |      dz  }t        t        j                  |            d }y # 1 sw Y   +xY w)Nr%   r&   5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}r(   r)   r*   r+   )r-   rh   r.   r/   r(   r*   r   r   r   r   r   r   r   r0   s        r!   r2   z(TestBB2_DockerCompose.test_is_valid_yamlj   s    ,1 	%R..$C	%#t$$$$$$$$z$$$z$$$$$$#$$$#$$$$$$t$$$t$$$$$$$$$$	% 	%s   EEc                   t        t        d      5 }t        j                  |      }d d d        t	        j                  di       j                               }h d}|j                  } ||      }|st        j                  d||z
         dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        t        j                  |            d x}}y # 1 sw Y   <xY w)	Nr%   r&   services>   lokigrafanapromtailrH   zMissing services: zL
>assert %(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.issubset
}(%(py3)s)
}required)r   r   r9   r;   )r-   rh   r.   r/   setrX   r>   issubsetr   r   r   r   r   r   r   r   )r   r1   r)   rl   rp   r   rY   rB   s           r!   test_has_all_four_servicesz0TestBB2_DockerCompose.test_has_all_four_serviceso   s>   ,1 	%R..$C	%swwz2.3356@   	
 * 	
* 	
  !H!4 56	
 	
	6	
 	
   	
 	
 		  	
 	
 		 ! 	
 	
	6	
 	
  "* 	
 	
 		 "* 	
 	
 		 + 	
 	
 	
 	
 	
		% 	%s   E""E,c                >   t        t        d      5 }t        j                  |      }ddd       d   d   }|j	                  dg       }d |D        }t        |      }|st        j                  d|       d	z   d
t        j                         v st        j                  t
              rt        j                  t
              nd
t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y# 1 sw Y   xY w)z.Grafana must use 3001:3000 to avoid conflicts.r%   r&   Nrl   rn   portsc              3  6   K   | ]  }d t        |      v   yw)3001Nstr.0ps     r!   	<genexpr>zDTestBB2_DockerCompose.test_grafana_uses_port_3001.<locals>.<genexpr>~        36SV#3   z*Grafana must expose port 3001, got ports: .
>assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyr   r-   rh   r.   r/   rX   r   r   r   r   r   r   r   r   r   )r   r1   r)   rn   ru   r   r   r    s           r!   test_grafana_uses_port_3001z1TestBB2_DockerCompose.test_grafana_uses_port_3001x   s    ,1 	%R..$C	%j/),GR(3U3 	
s33 	
3 	
  9@	
 	
	6	
 	
   	
 	
 		  	
 	
 		 4 	
 	
 		 4 	
 	
 	
 	
 	
		% 	%   DDc                >   t        t        d      5 }t        j                  |      }d d d        d   d   }|j	                  dg       }d |D        }t        |      }|st        j                  d|       dz   d	t        j                         v st        j                  t
              rt        j                  t
              nd	t        j                  |      t        j                  |      d
z  }t        t        j                  |            d x}}y # 1 sw Y   xY w)Nr%   r&   rl   rH   ru   c              3  6   K   | ]  }d t        |      v   yw)9090Nrx   rz   s     r!   r}   zGTestBB2_DockerCompose.test_prometheus_uses_port_9090.<locals>.<genexpr>   r~   r   z-Prometheus must expose port 9090, got ports: r   r   r   r   )r   r1   r)   rH   ru   r   r   r    s           r!   test_prometheus_uses_port_9090z4TestBB2_DockerCompose.test_prometheus_uses_port_9090   s    ,1 	%R..$C	%_\2
w+3U3 	
s33 	
3 	
  <E7C	
 	
	6	
 	
   	
 	
 		  	
 	
 		 4 	
 	
 		 4 	
 	
 	
 	
 	
		% 	%r   N)	r`   ra   rb   rc   r"   r2   rs   r   r   rd   r#   r!   rf   rf   b   s    P

%



r#   rf   c                      e Zd ZdZd Zd Zy)"TestBB3_GenesisMetricsNoDependencyzGBB3: GenesisMetrics initialises cleanly even without prometheus_client.c                8
   ddl }ddlmc m} |j                  }	 d|_        ddlm} |j                  |      }d|_        d|_        d|_	        |j                          |j                  }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      d	z  }	d
d|	iz  }
t%        t        j&                  |
            dx}x}}|j(                  }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      d	z  }	d
d|	iz  }
t%        t        j&                  |
            dx}x}}|j*                  }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      d	z  }	d
d|	iz  }
t%        t        j&                  |
            dx}x}}|j,                  }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      d	z  }	d
d|	iz  }
t%        t        j&                  |
            dx}x}}|j.                  }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      d	z  }	d
d|	iz  }
t%        t        j&                  |
            dx}x}}|j0                  }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      d	z  }	d
d|	iz  }
t%        t        j&                  |
            dx}x}}||_        y# ||_        w xY w)z/Simulate prometheus_client not being installed.r   NFGenesisMetricsgenesis)is not)z9%(py2)s
{%(py2)s = %(py0)s.request_count
} is not %(py5)sgmr   r   r;   assert %(py7)srU   )z;%(py2)s
{%(py2)s = %(py0)s.request_latency
} is not %(py5)s)z9%(py2)s
{%(py2)s = %(py0)s.active_agents
} is not %(py5)s)z:%(py2)s
{%(py2)s = %(py0)s.epoch_duration
} is not %(py5)s)z=%(py2)s
{%(py2)s = %(py0)s.kg_entities_total
} is not %(py5)s)z;%(py2)s
{%(py2)s = %(py0)s.llm_tokens_used
} is not %(py5)s)	importlibcore.observability.metricsobservabilitymetrics_PROMETHEUS_AVAILABLEr   __new__
_available
_namespace	_registry_init_noop_metricsrequest_countr   r<   r   r   r   r   r   r   request_latencyactive_agentsepoch_durationkg_entities_totalllm_tokens_used)r   r   metrics_modoriginal_availabler   r   r   rY   r   rB   @py_format8s              r!   /test_initializes_when_prometheus_client_missingzRTestBB3_GenesisMetricsNoDependency.test_initializes_when_prometheus_client_missing   s    	88(>>	C05K- B''7B!BM%BMBL!!# ##/4/#4////#4//////2///2///#///4///////%%1T1%T1111%T11111121112111%111T1111111##/4/#4////#4//////2///2///#///4///////$$0D0$D0000$D00000020002000$000D0000000''3t3't3333't33333323332333'333t3333333%%1T1%T1111%T11111121112111%111T11111110BK-0BK-s   S-T 	Tc                   ddl mc m} ddl m}m}m}m} |j                  |      }d|_        d|_	        d|_
        |j                          |j                  j                  ddd	      j                          |j                  j                  dd
      j!                  d       |j"                  j%                  d       |j"                  j                          |j"                  j'                          |j(                  j!                  d       |j*                  j%                  d       |j,                  j                  dd      j                  d       y)z9No-op instruments must accept labels() and measure calls.r   N)r   _NoOpCounter
_NoOpGauge_NoOpHistogramFr   GETz/health200methodendpointstatusr   r   g?   g      ?i  zgemini-flashgenerate)model	operationi  )r   r   r   r   r   r   r   r   r   r   r   r   r   labelsincr   observer   rq   decr   r   r   )r   r   r   r   r   r   r   s          r!   0test_all_instruments_callable_without_prometheuszSTestBB3_GenesisMetricsNoDependency.test_all_instruments_callable_without_prometheus   s   88	
 	
 ##N3!
 	uyOSSU
!!!CKKCP
Q


!!#&
  &
!!*!MQQRUVr#   N)r`   ra   rb   rc   r   r   rd   r#   r!   r   r      s    QC<Wr#   r   c                      e Zd ZdZd Zd Zy)"TestBB4_MetricsEndpointContentTypez=BB4: /metrics endpoint responds with text/plain Content-Type.c                ^   ddl m}  |       }t        |t              }|sddt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      nddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)	z8expose_metrics_text() must return a str without raising.r   expose_metrics_textrj   r(   resultry   r+   N)api.metrics_endpointr   r(   ry   r   r   r   r   r   r   r   )r   r   r   r   r    s        r!   'test_expose_metrics_text_returns_stringzJTestBB4_MetricsEndpointContentType.test_expose_metrics_text_returns_string   s    <$&&#&&&&&&&&z&&&z&&&&&&&&&&&&&&&&&#&&&#&&&&&&&&&&r#   c           
        	 ddl m} ddlm} |t	        j
                  d        ||      }|j                  d      }|j                  }d}||k(  }|st        j                  d|fd	||f      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}d}
|j                   }|j                  }d}d} |||      }|
|v }|st        j                  d|fd|
|f      t        j                  |
      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      t        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}x}x}x}x}}y# t"        $ r0 ddlm}  |       }t'        |t(              }|sddt        j                         v st        j                  t&              rt        j                  t&              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t(              rt        j                  t(              ndt        j                  |      dz  }t        t        j                  |            d}Y yw xY w)zCWhen FastAPI is available, the Response uses text/plain media_type.r   )
TestClient)appNzFastAPI not availablez/metrics   rI   )z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)sresponser   r   rU   z
text/plainzcontent-type r5   )zr%(py1)s in %(py13)s
{%(py13)s = %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s.headers
}.get
}(%(py9)s, %(py11)s)
})r,   r9   r;   rU   py9py11py13zassert %(py15)spy15r   rj   r(   r   ry   r+   )fastapi.testclientr   r   r   pytestskiprX   status_coder   r<   r   r   r   r   r   r   headersImportErrorr   r(   ry   )r   r   r   clientr   r   rY   r   rB   r   r?   rZ   r\   @py_assert10@py_assert12r@   @py_format14@py_format16r   r   r    s                        r!   test_content_type_is_text_plainzBTestBB4_MetricsEndpointContentType.test_content_type_is_text_plain   s   	+50{34_Fzz*-H''.3.'3....'3......8...8...'...3.......K8#3#3K#3#7#7KKK#7#KK<#KKKKK<#KKKK<KKKKKK8KKK8KKK#3KKK#7KKKKKKKKK#KKKKKKKKK 	+@(*Ffc********:***:******f***f******c***c**********	+s   H<H? ?D7M98M9N)r`   ra   rb   rc   r   r   rd   r#   r!   r   r      s    G'+r#   r   c                      e Zd ZdZd Zd Zy)TestWB1_CounterIncrementszEWB1: request_count Counter increments and the value is readable back.c                   t        j                  d       ddlm} ddlm}  | |             }|j                  j                  ddd	      j                          |j                  j                  ddd	      j                          |j                         }d
}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                   d      dz   d|iz  }t#        t        j$                  |            dx}}y)zAWhen prometheus_client IS available, the counter value increases.prometheus_clientr   CollectorRegistryr   registryr   /test2xxr   genesis_request_count_totalr5   r7   textr8   z+Counter name not found in exposition outputr:   r;   N)r   importorskipr   r   r   r   r   r   r   expose_metricsr   r<   r   r   r   r   r   r   r   	r   r   r   r   r   r?   r@   rA   rB   s	            r!   .test_counter_increments_with_prometheus_clientzHTestWB1_CounterIncrements.test_counter_increments_with_prometheus_client   s   /07=%6%89
uwuMQQS
uwuMQQS   ", 	
,4 	
 	
, 	
 	
 		 - 	
 	
	6	
 	
  15 	
 	
 		 15 	
 	
  :	
 	
 	
 	
 	
r#   c                    ddl m}  |       }t        d      D ]%  }|j                  ddd      j	                  d       ' y	)
z/No-op counter must silently absorb inc() calls.r   )r   d   POSTz/datar   r      N)r   r   ranger   r   )r   r   c_s       r!   0test_noop_counter_does_not_raise_on_repeated_inczJTestWB1_CounterIncrements.test_noop_counter_does_not_raise_on_repeated_inc  s>    ;Ns 	KAHHFWUHCGGJ	Kr#   N)r`   ra   rb   rc   r   r   rd   r#   r!   r   r      s    O
$Kr#   r   c                      e Zd ZdZd Zd Zy)TestWB2_HistogramObservez7WB2: request_latency Histogram records observed values.c                |   t        j                  d       ddlm} ddlm}  | |             }|j                  j                  dd      j                  d	       |j                  j                  dd      j                  d
       |j                         }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t!        t        j"                  |            dx}}y)zJWhen prometheus_client IS available, observe values appear in text output.r   r   r   r   r   r   z/pingr   g/$?gK7?genesis_request_latency_secondsr5   r7   r   r8   rR   r;   N)r   r   r   r   r   r   r   r   r   r   r   r<   r   r   r   r   r   r   r   s	            r!   -test_histogram_observe_with_prometheus_clientzFTestWB2_HistogramObserve.test_histogram_observe_with_prometheus_client  s    /07=%6%89
!!!AII%P
!!!AII%P  "080D88880D8880888888D888D8888888r#   c                p    ddl m}  |       }dD ]$  }|j                  dd      j                  |       & y)z5No-op histogram must silently absorb observe() calls.r   )r   )gMbP?g      ?g      ?g      @g      $@r   r   r   N)r   r   r   r   )r   r   hvs       r!   "test_noop_histogram_does_not_raisez;TestWB2_HistogramObserve.test_noop_histogram_does_not_raise+  s9    =- 	@AHHEGH4<<Q?	@r#   N)r`   ra   rb   rc   r   r   rd   r#   r!   r   r     s    A9@r#   r   c                      e Zd ZdZd Zd Zy)TestWB3_GracefulDegradationzIWB3: expose_metrics() returns '' when prometheus_client is not available.c                ,   ddl mc m} ddl m} |j	                  |      }d|_        d|_        d|_        |j                          |j                         }d}||k(  }|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
z  }t        j                   d|      dz   d|iz  }t#        t        j$                  |            dx}}y)z7With _available=False, expose_metrics() must return ''.r   Nr   Fr   r   rI   )z%(py0)s == %(py3)sr   )r   r9   z7Expected empty string from noop expose_metrics(), got: r:   r;   )r   r   r   r   r   r   r   r   r   r   r   r<   r   r   r   r   r   r   r   )	r   r   r   r   r   r@   r   rA   rB   s	            r!   ;test_expose_metrics_returns_empty_string_without_prometheuszWTestWB3_GracefulDegradation.test_expose_metrics_returns_empty_string_without_prometheus<  s    88=##N3!
""$ 	
v| 	
 	
v 	
 	
	6	
 	
   	
 	
 		  	
 	
 		  	
 	
  FfZP	
 	
 	
 	
 	
r#   c                ^   ddl m}  |       }t        |t              }|sddt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      nddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)	z@The module-level expose_metrics() function always returns a str.r   )r   rj   r(   r   ry   r+   N)r   r   r(   ry   r   r   r   r   r   r   r   )r   module_exposer   r   r    s        r!   'test_module_level_expose_returns_stringzCTestWB3_GracefulDegradation.test_module_level_expose_returns_stringL  s    N&#&&&&&&&&z&&&z&&&&&&&&&&&&&&&&&#&&&#&&&&&&&&&&r#   N)r`   ra   rb   rc   r   r   rd   r#   r!   r   r   9  s    S
 'r#   r   )#rc   
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   systypespathlibr   unittest.mockr   r   r   r.   __file__resolveparents
_REPO_ROOTry   pathinsert_MONITORING_DIRr   rh   r   rf   r   r   r   r   r   rd   r#   r!   <module>r     s   2 #   
   *  
 (^##%--a0
z?#(("HHOOAs:'
 w&5!$44!@@"= "=T'
 '
^9W 9WB+ +JK KH@ @<' 'r#   