def test_prometheus_metrics_counter(): metrics = PrometheusMetricsFactory(namespace='test') counter1 = metrics.create_counter(name='jaeger:test_counter', tags={'result': 'ok'}) counter1(1) counter2 = metrics.create_counter(name='jaeger:test_counter', tags={'result': 'ok'}) counter2(1) after = REGISTRY.get_sample_value('test_jaeger:test_counter', {'result': 'ok'}) assert 2 == after
def test_prometheus_metrics_guage(): metrics = PrometheusMetricsFactory(namespace='test') gauge = metrics.create_gauge(name='jaeger:test_gauge', tags={'result': 'ok'}) gauge(1) after = REGISTRY.get_sample_value('test_jaeger:test_gauge', {'result': 'ok'}) assert 1 == after
def test_prometheus_metrics_guage(): metrics = PrometheusMetricsFactory(namespace='test') gauge = metrics.create_gauge(name='jaeger:test_gauge', tags={'result': 'ok'}) gauge(1) after = REGISTRY.get_sample_value('test_jaeger:test_gauge', {'result': 'ok'}) assert 1 == after
def test_prometheus_metrics_counter(): metrics = PrometheusMetricsFactory(namespace='test') counter1 = metrics.create_counter(name='jaeger:test_counter', tags={'result': 'ok'}) counter1(1) counter2 = metrics.create_counter(name='jaeger:test_counter', tags={'result': 'ok'}) counter2(1) after = REGISTRY.get_sample_value('test_jaeger:test_counter', {'result': 'ok'}) assert 2 == after
def test_prometheus_metrics_metric_without_service_name_label(): metrics = PrometheusMetricsFactory() gauge = metrics.create_gauge( name='jaeger:test_gauge_without_service_name_label') gauge(1) gauge_after = REGISTRY.get_sample_value( 'jaeger:test_gauge_without_service_name_label') counter = metrics.create_counter( name='jaeger:test_counter_without_service_name_label') counter(1) counter_after = REGISTRY.get_sample_value( 'jaeger:test_counter_without_service_name_label') assert 1 == counter_after assert 1 == gauge_after
def __init__(self, service='osiris_egress_api'): reporting_host = config['Jaeger Agent']['reporting_host'] reporting_port = config['Jaeger Agent']['reporting_port'] local_agent = {} # Default empty - if run on localhost if reporting_host != 'localhost': local_agent['reporting_host'] = reporting_host local_agent['reporting_port'] = reporting_port tracer_config = Config( config={ 'sampler': { 'type': 'const', 'param': 1, }, 'local_agent': local_agent, 'logging': True, }, service_name=service, validate=True, # Adds some metrics to Prometheus metrics_factory=PrometheusMetricsFactory( service_name_label='osiris_egress_api')) self.tracer = tracer_config.initialize_tracer()
def bootstrap(name='MicroService'): log_level = logging.DEBUG logger = logging.getLogger('') logging.getLogger('').handlers = [] logging.basicConfig(format='%(asctime)s %(message)s', level=log_level) config = jConfig( config={ # usually read from some yaml config 'sampler': { 'type': 'const', 'param': 1, }, 'logging': True, }, service_name=name, validate=True, metrics_factory=PrometheusMetricsFactory(namespace=name), ) openapi_dict = load_yaml_file() app = App(name, use_tracer=config.initialize_tracer(), use_metric=True, use_optimizer=True, use_cors=True) app.add_api(openapi_dict, resolver=MultipleResourceResolver('api')) # set the WSGI application callable to allow using uWSGI: # uwsgi --http :8080 -w app # start "python Tutorial2.py" and open "http://localhost:8080/v1.0/" app.run(port=int(os.getenv("SERVER_PORT", 8080)))
def init_tracer(hs: "HomeServer"): """Set the whitelists and initialise the JaegerClient tracer""" global opentracing if not hs.config.opentracer_enabled: # We don't have a tracer opentracing = None return if not opentracing or not JaegerConfig: raise ConfigError( "The server has been configured to use opentracing but opentracing is not " "installed.") # Pull out the jaeger config if it was given. Otherwise set it to something sensible. # See https://github.com/jaegertracing/jaeger-client-python/blob/master/jaeger_client/config.py set_homeserver_whitelist(hs.config.opentracer_whitelist) from jaeger_client.metrics.prometheus import PrometheusMetricsFactory config = JaegerConfig( config=hs.config.jaeger_config, service_name=f"{hs.config.server_name} {hs.get_instance_name()}", scope_manager=LogContextScopeManager(hs.config), metrics_factory=PrometheusMetricsFactory(), ) # If we have the rust jaeger reporter available let's use that. if RustReporter: logger.info("Using rust_python_jaeger_reporter library") tracer = config.create_tracer(RustReporter(), config.sampler) opentracing.set_global_tracer(tracer) else: config.initialize_tracer()
def init_jaeger_tracer(self): """This scaffold is configured whith `Jeager <https://github.com/jaegertracing/jaeger>`_ but you can use one of the `opentracing tracers <http://opentracing.io/documentation/pages/supported-tracers.html>`_ :param service_name: the name of your application to register in the tracer :return: opentracing.Tracer """ check_package_exists("jaeger_client") Config = import_from("jaeger_client", "Config") host = {} if self.host: host = {'local_agent': {'reporting_host': self.host}} metrics_config = get_conf(service=get_service_name(service="metrics"), empty_init=True) metrics = "" if metrics_config: service_name = self.component_name.lower().replace("-", "_").replace( " ", "_") metrics = PrometheusMetricsFactory(service_name_label=service_name) config = Config(config={ **{ 'sampler': { 'type': 'const', 'param': 1, }, 'propagation': 'b3', 'logging': True }, **host }, service_name=self.component_name, metrics_factory=metrics, validate=True) return config.initialize_tracer()
def test_prometheus_metrics_metric_with_service_name_label(): metrics = PrometheusMetricsFactory(service_name_label='test') gauge = metrics.create_gauge( name='jaeger:test_gauge_with_service_name_label') gauge(1) gauge_after = REGISTRY.get_sample_value( 'jaeger:test_gauge_with_service_name_label', {'service': 'test'}) counter = metrics.create_counter( name='jaeger:test_counter_with_service_name_label', tags={'x': 'y'}) counter(1) counter_after = REGISTRY.get_sample_value( 'jaeger:test_counter_with_service_name_label', { 'service': 'test', 'x': 'y' }) assert 1 == counter_after assert 1 == gauge_after
def init_jaeger_tracer(service_name): """Create a Jaeger/OpenTracing configuration.""" config = JaegerConfig( config={ "sampler": {"type": "const", "param": 1}, "logging": True, "local_agent": {"reporting_host": Configuration.JAEGER_HOST}, }, service_name=service_name, validate=True, metrics_factory=PrometheusMetricsFactory(namespace=service_name), ) return config.initialize_tracer()
def initialize_jaeger(service_name): install_all_patches() config = Config( config={ "sampler": { "type": "const", "param": 1, }, "logging": True, }, service_name=service_name, validate=True, scope_manager=ContextVarsScopeManager(), metrics_factory=PrometheusMetricsFactory(namespace=service_name), ) return config.initialize_tracer()
def initialize_tracer(): install_all_patches() config = jaeger_client.Config( config={ 'sampler': { 'type': 'const', 'param': 1 }, 'logging': True, 'local_agent': { 'reporting_host': JAEGER_REPORTING_HOST, } }, service_name='tracebacks', validate=True, metrics_factory=PrometheusMetricsFactory(namespace='tracebacks'), ) return config.initialize_tracer() # also sets opentracing.tracer
def __init__( self, name, use_tracer=None, use_metric=False, use_logging_level=logging.DEBUG, use_optimizer=None, use_cors=None, use_default_error=None, use_scheduler=None, all=None, flaskName=None, *args, **kwargs, ): # TODO: Add more text here for current situation """ Initialize Flask App with multiple microservice-related and usability features. None is for deactivating, so it equals to False. *use_tracer* must be of type: bool (True for defaults, False for deactivating), opentracing.Tracer (use it for configuration), dict (use default opentracing.Tracer and the given dict as config) or defaults: None *use_metric* must be of type: bool (True for defaults, False for deactivating) or defaults: None *use_logging_level* must be of type: logging.{INFO, WARNING, ERROR, DEBUG}, defaults: DEBUG *use_optimizer* must be of type: bool (True for defaults, False for deactivating) or defaults: None *use_cors* must be of type: bool (True for defaults, False for deactivating) or defaults: None *use_default_error* must be of type: bool (True for defaults, False for deactivating) or defaults: None *use_scheduler* must be of type: bool (True for defaults, False for deactivating) or defaults: None *all* must be of type: bool (True for use all functions with defaults, False for deactivating all functions) or defaults: None """ if flaskName is None: flaskName = __name__ super().__init__(flaskName, *args, **kwargs) logger = logging.getLogger("") self.name = name self.metrics = None self.tracing = None self.optimize = None self.cors = None self.default_errorhandler = None self.scheduler = None if all is not None and all is not False: use_tracer = True use_metric = True use_optimizer = True use_cors = True use_default_error = True use_scheduler = True logger.info("--- Start Connexion-Plus ---") if not isinstance(self.app, (Flask, FlaskApp)): logger.warning( "Given App is not flask, so it cannot get any functionality added from this lib currently." ) return # add default error if use_default_error is not None and use_default_error is not False: from werkzeug.exceptions import HTTPException from werkzeug.exceptions import default_exceptions logger.info("Add default error handler to Flask...") if callable(use_default_error): self.default_errorhandler = use_default_error logger.info("use given handler.") else: def handle_error(e): code = 500 if isinstance(e, HTTPException): code = e.code error = { "error": e.__class__.__name__, "http_code": code, "description": str(e), } logger.exception(error) return jsonify(error), code self.default_errorhandler = handle_error logger.info("use default one") # register for all json exceptions self.app.register_error_handler(Exception, self.default_errorhandler) # register handler for all http exceptions for ex in default_exceptions: self.app.register_error_handler(ex, self.default_errorhandler) if use_scheduler is not None and use_scheduler is not False: logger.info("Add background scheduler to Flask") from flask_apscheduler import APScheduler self.scheduler = APScheduler() self.scheduler.init_app(self.app) self.scheduler.start() # add optimizer if use_optimizer is not None and use_optimizer is not False: logger.info("Add optimizer to Flask...") from .Optimizer import FlaskOptimize config = {"compress": False, "minify": False} if isinstance(use_optimizer, dict): config.update(use_optimizer) if isinstance(use_optimizer, bool) and use_optimizer: config.update({"compress": True, "minify": True}) logger.info("use config {}.".format(config)) self.optimize = FlaskOptimize(self.app, config) # add CORS if use_cors is not None and use_cors is not False: logger.info("Add cors to Flask...") from flask_cors import CORS if isinstance(use_cors, dict): logger.info("use given settings.") self.cors = CORS(self.app, resources=use_cors) else: logger.info("use default ones.") self.cors = CORS(self.app) logger.info("CORS added.") # add prometheus if use_metric is not None and use_metric is not False: # TODO: add configuration https://github.com/rycus86/prometheus_flask_exporter#configuration from prometheus_flask_exporter import PrometheusMetrics self.metrics = PrometheusMetrics(self.app) logger.info("Add prometheus to Flask") # add tracing if use_tracer is not None and use_tracer is not False: logger.info("Add opentracing to Flask...") # add tracing to all routes in flaskApp from flask_opentracing import FlaskTracing import opentracing from functools import wraps from flask import request def wrapper(fn): @wraps(fn) def request_func(*args, **kwargs): if request.path != "/metrics": return fn(*args, **kwargs) return request_func FlaskTracing._before_request_fn = wrapper( FlaskTracing._before_request_fn) FlaskTracing._after_request_fn = wrapper( FlaskTracing._after_request_fn) config = None if not isinstance(use_tracer, opentracing.Tracer): logger.info("use default one.") from jaeger_client import Config as jConfig tracer_config = { "sampler": { "type": "const", "param": 1, }, "local_agent": { "reporting_host": "jaeger-agent", "reporting_port": 5775, }, "logging": True, } if isinstance(use_tracer, dict): tracer_config = use_tracer if isinstance(use_metric, bool) and use_metric is True: logger.info("Use metrics for tracer.") from jaeger_client.metrics.prometheus import ( PrometheusMetricsFactory, ) config = jConfig( config=tracer_config, service_name=f"{name}ConnexionPlus", metrics_factory=PrometheusMetricsFactory( namespace=f"{name}ConnexionPlus"), ) else: logger.info("no metrics for tracer configured.") config = jConfig( config=tracer_config, service_name=f"{name}ConnexionPlus", ) else: logger.info("use given tracer config.") tracer_obj = use_tracer if config is None else config.initialize_tracer( ) self.tracing = FlaskTracing(tracer_obj, True, self.app) # add tracer to everything to support spans through multiple microservices via rpc-calls from opentracing_instrumentation.client_hooks import install_all_patches install_all_patches() logger.info("All tracing relevant libs patched.") # add a TracingHandler for Logging from .TracingHandler import TracingHandler th = TracingHandler(use_tracer) th.setLevel(use_logging_level) logging.getLogger("").addHandler(th) logger.info("Finished Tracer adding.") logger.info("--- Finished Connexion-Plus ---")
from connexion_plus import App from connexion.resolver import RestyResolver from jaeger_client import Config as jConfig from jaeger_client.metrics.prometheus import PrometheusMetricsFactory import logging config = jConfig( config={ 'logging': True, }, # use this, if you want to track your tracing itself with prometheus metrics_factory = PrometheusMetricsFactory(namespace=__name__), ) jaeger_tracer = config.initialize_tracer() app = App(__name__, use_tracer=jaeger_tracer, use_metric=True, use_logging_level=logging.DEBUG) app.add_api('openapi.yaml', resolver=RestyResolver('api')) app.run(port=8080, server='gevent')
def test_prometheus_metrics_counter_without_tags(): metrics = PrometheusMetricsFactory() counter = metrics.create_counter(name='jaeger:test_counter_no_tags') counter(1) after = REGISTRY.get_sample_value('jaeger:test_counter_no_tags') assert 1 == after
tracer_config = { "sampler": { "type": "const", "param": 1, }, "local_agent": { "reporting_host": "jaeger-agent", "reporting_port": 5775, }, "logging": True, } config = jConfig( config=tracer_config, service_name=f"RDSWebConnexionPlus", metrics_factory=PrometheusMetricsFactory(namespace=f"RDSWebConnexionPlus"), ) tracer_obj = config.initialize_tracer() tracing = FlaskTracing(tracer_obj, True, app) install_all_patches() # add a TracingHandler for Logging gunicorn_logger = logging.getLogger("gunicorn.error") app.logger.handlers.extend(gunicorn_logger.handlers) app.logger.addHandler(TracingHandler(tracer_obj)) app.logger.setLevel(gunicorn_logger.level) ### Tracing end ### app.config.update(flask_config)
def test_prometheus_metrics_gauge_without_tags(): metrics = PrometheusMetricsFactory() gauge = metrics.create_gauge(name='jaeger:test_gauge_no_tags') gauge(1) after = REGISTRY.get_sample_value('jaeger:test_gauge_no_tags') assert 1 == after
def test_prometheus_metrics_counter_without_tags(): metrics = PrometheusMetricsFactory() counter = metrics.create_counter(name='jaeger:test_counter_no_tags') counter(1) after = REGISTRY.get_sample_value('jaeger:test_counter_no_tags') assert 1 == after
def test_prometheus_metrics_gauge_without_tags(): metrics = PrometheusMetricsFactory() gauge = metrics.create_gauge(name='jaeger:test_gauge_no_tags') gauge(1) after = REGISTRY.get_sample_value('jaeger:test_gauge_no_tags') assert 1 == after