Example #1
0
def configure_tracing(configuration: dict):
    # OTLP Exporter configuration
    if configuration['exporter'] == 'otlp':
        service_name = {'service.name': configuration['service_name']}
        resource = Resource(service_name)
        trace.set_tracer_provider(TracerProvider(resource=resource))
        exporter = OTLPSpanExporter(
            endpoint=configuration['exporter_endpoint'],
            insecure=configuration['exporter_insecure'])
        trace.get_tracer(__name__)
        span_processor = BatchExportSpanProcessor(exporter)
        trace.get_tracer_provider().add_span_processor(span_processor)

    # Jaeger HTTP Exporter configuration
    elif configuration['exporter'] == 'jaeger_http':
        exporter = JaegerSpanExporter(
            service_name=configuration['service_name'],
            collector_endpoint=configuration['exporter_endpoint'],
        )
        trace.set_tracer_provider(TracerProvider())
        trace.get_tracer(__name__)
        span_processor = BatchExportSpanProcessor(exporter)
        trace.get_tracer_provider().add_span_processor(span_processor)

    # Jaeger Thrifth Compact Exporter configuration
    elif configuration['exporter'] == 'jaeger_thrift':
        exporter = JaegerSpanExporter(
            service_name=configuration['service_name'],
            agent_host_name=configuration['exporter_host'],
            agent_port=configuration['exporter_port'],
        )
        trace.set_tracer_provider(TracerProvider())
        trace.get_tracer(__name__)
        span_processor = BatchExportSpanProcessor(exporter)
        trace.get_tracer_provider().add_span_processor(span_processor)

    # Zipkin Exporter configuration
    elif configuration['exporter'] == 'zipkin':
        exporter = ZipkinSpanExporter(
            service_name=configuration['service_name'],
            url=configuration['exporter_endpoint'])
        trace.set_tracer_provider(TracerProvider())
        trace.get_tracer(__name__)
        span_processor = BatchExportSpanProcessor(exporter)
        trace.get_tracer_provider().add_span_processor(span_processor)

    # Console Exporter configuration
    elif configuration['exporter'] == 'console':
        trace.set_tracer_provider(TracerProvider())
        trace.get_tracer_provider().add_span_processor(
            SimpleExportSpanProcessor(ConsoleSpanExporter()))
    else:
        raise ValueError(
            'Only Otlp, Jaeger Thrift/HTTP and Zipkin exporters are supported. '
            'Please check your configuration.')
Example #2
0
def init_tracing(service_name):
    if Config.TRACE_EXPORTER is None:
        return
    elif Config.TRACE_EXPORTER == 'jaeger':
        exporter = JaegerSpanExporter(
            service_name=service_name,
            agent_host_name=Config.JAEGER_HOST,
            agent_port=6831,
        )
    elif Config.TRACE_EXPORTER == 'honeycomb':
        exporter = HoneycombSpanExporter(
            service_name=service_name,
            writekey=Config.HONEYCOMB_API_KEY,
            dataset=Config.HONEYCOMB_DATASET,
        )
    else:
        raise ValueError(
            f"TRACE_EXPORTER {Config.TRACE_EXPORTER} is not valid")

    trace.set_tracer_provider(TracerProvider())
    span_processor = BatchExportSpanProcessor(exporter)
    trace.get_tracer_provider().add_span_processor(span_processor)

    # This isn't great but oh well
    global tracer
    tracer = trace.get_tracer(service_name)
def main():
    model_name = "my-model"
    model_version = "v1"
    client = sczpy.SCZClient(server_url)

    trace.set_tracer_provider(TracerProvider())

    jaeger_exporter = jaeger.JaegerSpanExporter(
        service_name="my-device",
        agent_host_name="localhost",
        agent_port=6831,
    )

    trace.get_tracer_provider().add_span_processor(
        BatchExportSpanProcessor(jaeger_exporter))
    trace.get_tracer_provider().add_span_processor(
        SimpleExportSpanProcessor(sczpy.SCZSpanExporter(client)))
    tracer = trace.get_tracer(__name__)

    while True:
        with tracer.start_as_current_span("inference") as inference:
            inference.set_attribute('device', 'my-device')
            inference.add_event(
                'inference', {
                    "confidence": random.randint(80, 101),
                    "model_name": model_name,
                    "model_version": model_version,
                    "file_ref": "dummy_data.txt"
                })
        time.sleep(3)
Example #4
0
def get_otel_tracer():

    set_global_textmap(CompositeHTTPPropagator([B3Format()]))
    span_exporter = get_otlp_exporter()

    trace.get_tracer_provider().add_span_processor(
        BatchExportSpanProcessor(span_exporter))
    return trace.get_tracer(__name__)
Example #5
0
def otel_init():
    global tracer
    jaeger_exporter = jaeger.JaegerSpanExporter(service_name='py_kc',
                                                agent_host_name='timemachine',
                                                agent_port=6831)
    trace.set_tracer_provider(TracerProvider(sampler=sampling.ALWAYS_ON))
    span_processor = BatchExportSpanProcessor(jaeger_exporter)
    trace.get_tracer_provider().add_span_processor(span_processor)
    tracer = trace.get_tracer(__name__)
Example #6
0
def init_tracer():
    from opentelemetry.ext.jaeger import JaegerSpanExporter

    exporter = JaegerSpanExporter(
        service_name="basic", agent_host_name="localhost", agent_port=6831
    )

    trace.set_tracer_provider(TracerProvider())
    span_processor = BatchExportSpanProcessor(exporter)
    trace.get_tracer_provider().add_span_processor(span_processor)
Example #7
0
def init_tracing():
  global initialized
  if initialized:
    return
  initialized = True

  provider = TracerProvider()
  trace.set_tracer_provider(provider)

  provider.add_span_processor(BatchExportSpanProcessor(ConsoleSpanExporter()))
  auto_instrument()
Example #8
0
def setup_tracer(service_name):
    jaeger_exporter = jaeger.JaegerSpanExporter(
        service_name=service_name,
        # configure agent
        agent_host_name='jaeger',
        agent_port=6831,
    )
    span_processor = BatchExportSpanProcessor(jaeger_exporter)

    trace.set_preferred_tracer_source_implementation(lambda T: TracerSource())
    trace.tracer_source().add_span_processor(span_processor)

    postgres_tracer = trace.tracer_source().get_tracer('postgres')
    trace_integration(postgres_tracer)
def set_up(service_name: str):
    """Instantiate and configure the span exporter.

    The exporter is select and configured through environment variables.

    Parameters
    ----------
    service_name : str
        The name under which the data is exported.
    """
    if tracing_settings.TRACING_EXPORTER.lower() == "jaeger":
        from opentelemetry.sdk.trace.export import BatchExportSpanProcessor

        jaeger_exporter = jaeger.JaegerSpanExporter(
            service_name=service_name,
            agent_host_name=tracing_settings.JAEGER_AGENT_HOST_NAME,
            agent_port=tracing_settings.JAEGER_AGENT_PORT,
        )

        trace.get_tracer_provider().add_span_processor(
            BatchExportSpanProcessor(jaeger_exporter))
    elif tracing_settings.TRACING_EXPORTER.lower() == "console":
        from opentelemetry.sdk.trace.export import SimpleExportSpanProcessor, ConsoleSpanExporter

        trace.get_tracer_provider().add_span_processor(
            SimpleExportSpanProcessor(ConsoleSpanExporter()))
    elif tracing_settings.TRACING_EXPORTER == "gcp":
        from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
        from opentelemetry.tools.cloud_trace_propagator import CloudTraceFormatPropagator
        from opentelemetry.sdk.trace.export import BatchExportSpanProcessor
        from opentelemetry.propagators import set_global_textmap

        cloud_trace_exporter = CloudTraceSpanExporter()
        trace.get_tracer_provider().add_span_processor(
            BatchExportSpanProcessor(cloud_trace_exporter))

        set_global_textmap(CloudTraceFormatPropagator())
Example #10
0
 async def __aenter__(self):
     exporter = JaegerSpanExporter(
         service_name=self._config.service_name,
         agent_host_name=self._config.address.host,
         agent_port=self._config.address.port,
     )
     span_processor = BatchExportSpanProcessor(exporter)
     source: TracerProvider = get_tracer_provider()
     source.add_span_processor(span_processor)
     _log.info(
         "%s started: service_name=%s; addr=%s:%d",
         self.__class__.__name__,
         self._config.service_name,
         self._config.address.host,
         self._config.address.port,
     )
Example #11
0
def create_grpc_server(is_prod: bool) -> grpc.Server:
    console_span_processor = SimpleExportSpanProcessor(ConsoleSpanExporter())
    if is_prod:
        span_processor = MultiSpanProcessor()
        span_processor.add_span_processor(console_span_processor)
        span_processor.add_span_processor(
            BatchExportSpanProcessor(CloudTraceSpanExporter()))
    else:
        span_processor = console_span_processor

    # this should typecheck but the API interface doesn't have add_span_processor()
    trace.get_tracer_provider().add_span_processor(  # type: ignore
        span_processor)

    server = grpc.server(ThreadPoolExecutor(max_workers=10))
    server = intercept_server(server, server_interceptor())
    return server
Example #12
0
def _init_tracing(exporters: Sequence[SpanExporter],
                  ids_generator: IdsGenerator):
    service_name = _get_service_name()
    provider = TracerProvider(
        resource=Resource.create({"service.name": service_name}),
        ids_generator=ids_generator(),
    )
    trace.set_tracer_provider(provider)

    for exporter_name, exporter_class in exporters.items():
        exporter_args = {}
        if exporter_name not in [
                EXPORTER_OTLP,
                EXPORTER_OTLP_SPAN,
        ]:
            exporter_args["service_name"] = service_name

        provider.add_span_processor(
            BatchExportSpanProcessor(exporter_class(**exporter_args)))
Example #13
0
def get_application() -> FastAPI:

    trace.set_tracer_provider(TracerProvider())
    jaeger_exporter = JaegerSpanExporter(
        service_name="Jaeger Demo App",
        agent_host_name="jaeger-agent",
        agent_port=6831
        #service_name="Jaeger Demo App", collector_endpoint="http://localhost:31298/api/traces"
    )
    trace.get_tracer_provider().add_span_processor(
        BatchExportSpanProcessor(jaeger_exporter, max_export_batch_size=10))

    application = FastAPI(title="Jaeger Demo App",
                          description="Jaeger Demo App Entrypoiny",
                          openapi_url="/openapi.json",
                          docs_url="/docs")

    # Add your routers
    FastAPIInstrumentor.instrument_app(application)
    return application
Example #14
0
def init(conf):
    trace.set_tracer_provider(TracerProvider())
    # https://opentelemetry-python.readthedocs.io/en/stable/exporter/jaeger/jaeger.html
    # create a JaegerSpanExporter
    jaeger_exporter = jaeger.JaegerSpanExporter(
        service_name=conf['service_name'],
        # configure agent
        agent_host_name=conf['agent_host_name'],
        agent_port=conf['agent_port'],
        # optional: configure also collector
        # collector_host_name='localhost',
        # collector_port=14268,
        # collector_endpoint='/api/traces?format=jaeger.thrift',
        # collector_protocol='http',
        # username=xxxx, # optional
        # password=xxxx, # optional
    )
    # Create a BatchExportSpanProcessor and add the exporter to it
    span_processor = BatchExportSpanProcessor(jaeger_exporter)
    # add to the tracer
    trace.get_tracer_provider().add_span_processor(span_processor)
Example #15
0
    def __init__(
        self,
        type: Text = None,
        service_name: Text = "rasa",
        agent_host_name: Text = "localhost",
        agent_port: int = 6831,
    ):
        self.type = type
        if self.type == "open_telemetry":
            trace.set_tracer_provider(TracerProvider())

            jaeger_exporter = jaeger.JaegerSpanExporter(
                service_name=service_name,
                agent_host_name=agent_host_name,
                agent_port=agent_port,
            )

            trace.get_tracer_provider().add_span_processor(
                BatchExportSpanProcessor(jaeger_exporter)
            )

            # self.tracer = trace.get_tracer(__name__)
            self.tracer = trace.get_tracer(__name__)
            logger.debug(f"Tracer - exit init, name: {__name__}")
        elif self.type == "jaeger":
            config = Config(
                config={  # usually read from some yaml config
                    "sampler": {
                        "type": "const",
                        "param": 1,
                    },
                    "logging": True,
                },
                service_name=service_name,
                validate=True,
            )

            # this call also sets opentracing.tracer
            self.tracer = config.initialize_tracer()
Example #16
0
def init_jaeger(jaeger_host: str, service_name):
    trace.set_tracer_provider(TracerProvider())
    tracer = trace.get_tracer_provider().get_tracer(__name__)
    # trace.get_tracer_provider().add_span_processor(
    #     BatchExportSpanProcessor(ConsoleSpanExporter())
    # )
    # create a JaegerSpanExporter
    jaeger_exporter = jaeger.JaegerSpanExporter(
        service_name=service_name,
        # configure agent
        agent_host_name=jaeger_host,
        agent_port=6831,
        # optional: configure also collector
        # collector_host_name='localhost',
        # collector_port=14268,
        # collector_endpoint='/api/traces?format=jaeger.thrift',
        # username=xxxx, # optional
        # password=xxxx, # optional
    )
    # Create a BatchExportSpanProcessor and add the exporter to it
    span_processor = BatchExportSpanProcessor(jaeger_exporter)
    # add to the tracer
    trace.get_tracer_provider().add_span_processor(span_processor)
    return tracer
Example #17
0
def direct_message_consume(messaging_service: MessagingService,
                           topic_subscription: str):
    try:
        trace.set_tracer_provider(TracerProvider())
        jaeger_exporter = jaeger.JaegerSpanExporter(
            service_name="<Solace> REST Messaging call to Security Co",
            agent_host_name="localhost",
            agent_port=6831,
        )

        trace.get_tracer_provider().add_span_processor(
            BatchExportSpanProcessor(jaeger_exporter))

        tracer = trace.get_tracer(__name__)

        topics = [TopicSubscription.of(topic_subscription)]

        # Create a direct message consumer service with the topic subscription and start it
        direct_receive_service = messaging_service.create_direct_message_receiver_builder(
        )
        direct_receive_service = direct_receive_service.with_subscriptions(
            topics).build()
        direct_receive_service.start()

        # Register a callback message handler
        direct_receive_service.receive_async(MessageHandlerImpl())
        print(f"Subscribed to: {topic_subscription}")
        # Infinite loop until Keyboard interrupt is received
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            print('\nDisconnecting Messaging Service')
    finally:
        messaging_service.disconnect()
        direct_receive_service.terminate()
Example #18
0
def create_app():
    """Flask application factory to create instances
    of the Userservice Flask App
    """
    app = Flask(__name__)

    # Disabling unused-variable for lines with route decorated functions
    # as pylint thinks they are unused
    # pylint: disable=unused-variable
    @app.route('/version', methods=['GET'])
    def version():
        """
        Service version endpoint
        """
        return app.config['VERSION'], 200

    @app.route('/ready', methods=['GET'])
    def readiness():
        """
        Readiness probe
        """
        return 'ok', 200

    @app.route('/users', methods=['POST'])
    def create_user():
        """Create a user record.

        Fails if that username already exists.

        Generates a unique accountid.

        request fields:
        - username
        - password
        - password-repeat
        - firstname
        - lastname
        - birthday
        - timezone
        - address
        - state
        - zip
        - ssn
        """
        try:
            app.logger.debug('Sanitizing input.')
            req = {k: bleach.clean(v) for k, v in request.form.items()}
            __validate_new_user(req)
            # Check if user already exists
            if users_db.get_user(req['username']) is not None:
                raise NameError('user {} already exists'.format(
                    req['username']))

            # Create password hash with salt
            app.logger.debug("Creating password hash.")
            password = req['password']
            salt = bcrypt.gensalt()
            passhash = bcrypt.hashpw(password.encode('utf-8'), salt)

            accountid = users_db.generate_accountid()

            # Create user data to be added to the database
            user_data = {
                'accountid': accountid,
                'username': req['username'],
                'passhash': passhash,
                'firstname': req['firstname'],
                'lastname': req['lastname'],
                'birthday': req['birthday'],
                'timezone': req['timezone'],
                'address': req['address'],
                'state': req['state'],
                'zip': req['zip'],
                'ssn': req['ssn'],
            }
            # Add user_data to database
            app.logger.debug("Adding user to the database")
            users_db.add_user(user_data)
            app.logger.info("Successfully created user.")

        except UserWarning as warn:
            app.logger.error("Error creating new user: %s", str(warn))
            return str(warn), 400
        except NameError as err:
            app.logger.error("Error creating new user: %s", str(err))
            return str(err), 409
        except SQLAlchemyError as err:
            app.logger.error("Error creating new user: %s", str(err))
            return 'failed to create user', 500

        return jsonify({}), 201

    def __validate_new_user(req):
        app.logger.debug('validating create user request: %s', str(req))
        # Check if required fields are filled
        fields = (
            'username',
            'password',
            'password-repeat',
            'firstname',
            'lastname',
            'birthday',
            'timezone',
            'address',
            'state',
            'zip',
            'ssn',
        )
        if any(f not in req for f in fields):
            raise UserWarning('missing required field(s)')
        if any(not bool(req[f] or req[f].strip()) for f in fields):
            raise UserWarning('missing value for input field(s)')

        # Verify username contains only 2-15 alphanumeric or underscore characters
        if not re.match(r"\A[a-zA-Z0-9_]{2,15}\Z", req['username']):
            raise UserWarning(
                'username must contain 2-15 alphanumeric characters or underscores'
            )
        # Check if passwords match
        if not req['password'] == req['password-repeat']:
            raise UserWarning('passwords do not match')

    @app.route('/login', methods=['GET'])
    def login():
        """Login a user and return a JWT token

        Fails if username doesn't exist or password doesn't match hash

        token expiry time determined by environment variable

        request fields:
        - username
        - password
        """
        app.logger.debug('Sanitizing login input.')
        username = bleach.clean(request.args.get('username'))
        password = bleach.clean(request.args.get('password'))

        # Get user data
        try:
            app.logger.debug('Getting the user data.')
            user = users_db.get_user(username)
            if user is None:
                raise LookupError('user {} does not exist'.format(username))

            # Validate the password
            app.logger.debug('Validating the password.')
            if not bcrypt.checkpw(password.encode('utf-8'), user['passhash']):
                raise PermissionError('invalid login')

            full_name = '{} {}'.format(user['firstname'], user['lastname'])
            exp_time = datetime.utcnow() + timedelta(
                seconds=app.config['EXPIRY_SECONDS'])
            payload = {
                'user': username,
                'acct': user['accountid'],
                'name': full_name,
                'iat': datetime.utcnow(),
                'exp': exp_time,
            }
            app.logger.debug('Creating jwt token.')
            token = jwt.encode(payload,
                               app.config['PRIVATE_KEY'],
                               algorithm='RS256')
            app.logger.info('Login Successful.')
            return jsonify({'token': token.decode("utf-8")}), 200

        except LookupError as err:
            app.logger.error('Error logging in: %s', str(err))
            return str(err), 404
        except PermissionError as err:
            app.logger.error('Error logging in: %s', str(err))
            return str(err), 401
        except SQLAlchemyError as err:
            app.logger.error('Error logging in: %s', str(err))
            return 'failed to retrieve user information', 500

    @atexit.register
    def _shutdown():
        """Executed when web app is terminated."""
        app.logger.info("Stopping userservice.")

    # Set up logger
    app.logger.handlers = logging.getLogger('gunicorn.error').handlers
    app.logger.setLevel(logging.getLogger('gunicorn.error').level)
    app.logger.info('Starting userservice.')

    # Set up tracing and export spans to Cloud Trace.
    if os.environ['ENABLE_TRACING'] == "true":
        app.logger.info("✅ Tracing enabled.")
        # Set up tracing and export spans to Cloud Trace
        trace.set_tracer_provider(TracerProvider())
        cloud_trace_exporter = CloudTraceSpanExporter()
        trace.get_tracer_provider().add_span_processor(
            BatchExportSpanProcessor(cloud_trace_exporter))
        set_global_textmap(CloudTraceFormatPropagator())
        FlaskInstrumentor().instrument_app(app)
    else:
        app.logger.info("🚫 Tracing disabled.")

    app.config['VERSION'] = os.environ.get('VERSION')
    app.config['EXPIRY_SECONDS'] = int(os.environ.get('TOKEN_EXPIRY_SECONDS'))
    app.config['PRIVATE_KEY'] = open(os.environ.get('PRIV_KEY_PATH'),
                                     'r').read()
    app.config['PUBLIC_KEY'] = open(os.environ.get('PUB_KEY_PATH'), 'r').read()

    # Configure database connection
    try:
        users_db = UserDb(os.environ.get("ACCOUNTS_DB_URI"), app.logger)
    except OperationalError:
        app.logger.critical("users_db database connection failed")
        sys.exit(1)
    return app
Example #19
0
def create_app():
    """Flask application factory to create instances
    of the Frontend Flask App
    """
    app = Flask(__name__)

    # Disabling unused-variable for lines with route decorated functions
    # as pylint thinks they are unused
    # pylint: disable=unused-variable
    @app.route('/version', methods=['GET'])
    def version():
        """
        Service version endpoint
        """
        return os.environ.get('VERSION'), 200

    @app.route('/ready', methods=['GET'])
    def readiness():
        """
        Readiness probe
        """
        return 'ok', 200

    @app.route("/")
    def root():
        """
        Renders home page or login page, depending on authentication status.
        """
        token = request.cookies.get(app.config['TOKEN_NAME'])
        if not verify_token(token):
            return login_page()
        return home()

    @app.route("/home")
    def home():
        """
        Renders home page. Redirects to /login if token is not valid
        """
        token = request.cookies.get(app.config['TOKEN_NAME'])
        if not verify_token(token):
            # user isn't authenticated
            app.logger.debug(
                'User isn\'t authenticated. Redirecting to login page.')
            return redirect(
                url_for('login_page',
                        _external=True,
                        _scheme=app.config['SCHEME']))
        token_data = jwt.decode(token, verify=False)
        display_name = token_data['name']
        username = token_data['user']
        account_id = token_data['acct']

        hed = {'Authorization': 'Bearer ' + token}
        # get balance
        balance = None
        try:
            url = '{}/{}'.format(app.config["BALANCES_URI"], account_id)
            app.logger.debug('Getting account balance.')
            response = requests.get(url=url,
                                    headers=hed,
                                    timeout=app.config['BACKEND_TIMEOUT'])
            if response:
                balance = response.json()
        except (requests.exceptions.RequestException, ValueError) as err:
            app.logger.error('Error getting account balance: %s', str(err))
        # get history
        transaction_list = None
        try:
            url = '{}/{}'.format(app.config["HISTORY_URI"], account_id)
            app.logger.debug('Getting transaction history.')
            response = requests.get(url=url,
                                    headers=hed,
                                    timeout=app.config['BACKEND_TIMEOUT'])
            if response:
                transaction_list = response.json()
        except (requests.exceptions.RequestException, ValueError) as err:
            app.logger.error('Error getting transaction history: %s', str(err))
        # get contacts
        contacts = []
        try:
            url = '{}/{}'.format(app.config["CONTACTS_URI"], username)
            app.logger.debug('Getting contacts.')
            response = requests.get(url=url,
                                    headers=hed,
                                    timeout=app.config['BACKEND_TIMEOUT'])
            if response:
                contacts = response.json()
        except (requests.exceptions.RequestException, ValueError) as err:
            app.logger.error('Error getting contacts: %s', str(err))

        _populate_contact_labels(account_id, transaction_list, contacts)

        return render_template('index.html',
                               cymbal_logo=os.getenv('CYMBAL_LOGO', 'false'),
                               history=transaction_list,
                               balance=balance,
                               name=display_name,
                               account_id=account_id,
                               contacts=contacts,
                               message=request.args.get('msg', None),
                               bank_name=os.getenv('BANK_NAME',
                                                   'Bank of Anthos'))

    def _populate_contact_labels(account_id, transactions, contacts):
        """
        Populate contact labels for the passed transactions.

        Side effect:
            Take each transaction and set the 'accountLabel' field with the label of
            the contact each transaction was associated with. If there was no
            associated contact, set 'accountLabel' to None.
            If any parameter is None, nothing happens.

        Params: account_id - the account id for the user owning the transaction list
                transactions - a list of transactions as key/value dicts
                            [{transaction1}, {transaction2}, ...]
                contacts - a list of contacts as key/value dicts
                        [{contact1}, {contact2}, ...]
        """
        app.logger.debug('Populating contact labels.')
        if account_id is None or transactions is None or contacts is None:
            return

        # Map contact accounts to their labels. If no label found, default to None.
        contact_map = {c['account_num']: c.get('label') for c in contacts}

        # Populate the 'accountLabel' field. If no match found, default to None.
        for trans in transactions:
            if trans['toAccountNum'] == account_id:
                trans['accountLabel'] = contact_map.get(
                    trans['fromAccountNum'])
            elif trans['fromAccountNum'] == account_id:
                trans['accountLabel'] = contact_map.get(trans['toAccountNum'])

    @app.route('/payment', methods=['POST'])
    def payment():
        """
        Submits payment request to ledgerwriter service

        Fails if:
        - token is not valid
        - basic validation checks fail
        - response code from ledgerwriter is not 201
        """
        token = request.cookies.get(app.config['TOKEN_NAME'])
        if not verify_token(token):
            # user isn't authenticated
            app.logger.error(
                'Error submitting payment: user is not authenticated.')
            return abort(401)
        try:
            account_id = jwt.decode(token, verify=False)['acct']
            recipient = request.form['account_num']
            if recipient == 'add':
                recipient = request.form['contact_account_num']
                label = request.form.get('contact_label', None)
                if label:
                    # new contact. Add to contacts list
                    _add_contact(label, recipient, app.config['LOCAL_ROUTING'],
                                 False)

            transaction_data = {
                "fromAccountNum": account_id,
                "fromRoutingNum": app.config['LOCAL_ROUTING'],
                "toAccountNum": recipient,
                "toRoutingNum": app.config['LOCAL_ROUTING'],
                "amount": int(Decimal(request.form['amount']) * 100),
                "uuid": request.form['uuid']
            }
            _submit_transaction(transaction_data)
            app.logger.info('Payment initiated successfully.')
            return redirect(
                url_for('home',
                        msg='Payment successful',
                        _external=True,
                        _scheme=app.config['SCHEME']))

        except requests.exceptions.RequestException as err:
            app.logger.error('Error submitting payment: %s', str(err))
        except UserWarning as warn:
            app.logger.error('Error submitting payment: %s', str(warn))
            msg = 'Payment failed: {}'.format(str(warn))
            return redirect(
                url_for('home',
                        msg=msg,
                        _external=True,
                        _scheme=app.config['SCHEME']))

        return redirect(
            url_for('home',
                    msg='Payment failed',
                    _external=True,
                    _scheme=app.config['SCHEME']))

    @app.route('/deposit', methods=['POST'])
    def deposit():
        """
        Submits deposit request to ledgerwriter service

        Fails if:
        - token is not valid
        - routing number == local routing number
        - response code from ledgerwriter is not 201
        """
        token = request.cookies.get(app.config['TOKEN_NAME'])
        if not verify_token(token):
            # user isn't authenticated
            app.logger.error(
                'Error submitting deposit: user is not authenticated.')
            return abort(401)
        try:
            # get account id from token
            account_id = jwt.decode(token, verify=False)['acct']
            if request.form['account'] == 'add':
                external_account_num = request.form['external_account_num']
                external_routing_num = request.form['external_routing_num']
                if external_routing_num == app.config['LOCAL_ROUTING']:
                    raise UserWarning("invalid routing number")
                external_label = request.form.get('external_label', None)
                if external_label:
                    # new contact. Add to contacts list
                    _add_contact(external_label, external_account_num,
                                 external_routing_num, True)
            else:
                account_details = json.loads(request.form['account'])
                external_account_num = account_details['account_num']
                external_routing_num = account_details['routing_num']

            transaction_data = {
                "fromAccountNum": external_account_num,
                "fromRoutingNum": external_routing_num,
                "toAccountNum": account_id,
                "toRoutingNum": app.config['LOCAL_ROUTING'],
                "amount": int(Decimal(request.form['amount']) * 100),
                "uuid": request.form['uuid']
            }
            _submit_transaction(transaction_data)
            app.logger.info('Deposit submitted successfully.')
            return redirect(
                url_for('home',
                        msg='Deposit successful',
                        _external=True,
                        _scheme=app.config['SCHEME']))

        except requests.exceptions.RequestException as err:
            app.logger.error('Error submitting deposit: %s', str(err))
        except UserWarning as warn:
            app.logger.error('Error submitting deposit: %s', str(warn))
            msg = 'Deposit failed: {}'.format(str(warn))
            return redirect(
                url_for('home',
                        msg=msg,
                        _external=True,
                        _scheme=app.config['SCHEME']))

        return redirect(
            url_for('home',
                    msg='Deposit failed',
                    _external=True,
                    _scheme=app.config['SCHEME']))

    def _submit_transaction(transaction_data):
        app.logger.debug('Submitting transaction.')
        token = request.cookies.get(app.config['TOKEN_NAME'])
        hed = {
            'Authorization': 'Bearer ' + token,
            'content-type': 'application/json'
        }
        resp = requests.post(url=app.config["TRANSACTIONS_URI"],
                             data=jsonify(transaction_data).data,
                             headers=hed,
                             timeout=app.config['BACKEND_TIMEOUT'])
        try:
            resp.raise_for_status()  # Raise on HTTP Status code 4XX or 5XX
        except requests.exceptions.HTTPError:
            raise UserWarning(resp.text)

    def _add_contact(label, acct_num, routing_num, is_external_acct=False):
        """
        Submits a new contact to the contact service.

        Raise: UserWarning  if the response status is 4xx or 5xx.
        """
        app.logger.debug('Adding new contact.')
        token = request.cookies.get(app.config['TOKEN_NAME'])
        hed = {
            'Authorization': 'Bearer ' + token,
            'content-type': 'application/json'
        }
        contact_data = {
            'label': label,
            'account_num': acct_num,
            'routing_num': routing_num,
            'is_external': is_external_acct
        }
        token_data = jwt.decode(token, verify=False)
        url = '{}/{}'.format(app.config["CONTACTS_URI"], token_data['user'])
        resp = requests.post(url=url,
                             data=jsonify(contact_data).data,
                             headers=hed,
                             timeout=app.config['BACKEND_TIMEOUT'])
        try:
            resp.raise_for_status()  # Raise on HTTP Status code 4XX or 5XX
        except requests.exceptions.HTTPError:
            raise UserWarning(resp.text)

    @app.route("/login", methods=['GET'])
    def login_page():
        """
        Renders login page. Redirects to /home if user already has a valid token
        """
        token = request.cookies.get(app.config['TOKEN_NAME'])
        if verify_token(token):
            # already authenticated
            app.logger.debug(
                'User already authenticated. Redirecting to /home')
            return redirect(
                url_for('home', _external=True, _scheme=app.config['SCHEME']))

        return render_template('login.html',
                               cymbal_logo=os.getenv('CYMBAL_LOGO', 'false'),
                               message=request.args.get('msg', None),
                               default_user=os.getenv('DEFAULT_USERNAME', ''),
                               default_password=os.getenv(
                                   'DEFAULT_PASSWORD', ''),
                               bank_name=os.getenv('BANK_NAME',
                                                   'Bank of Anthos'))

    @app.route('/login', methods=['POST'])
    def login():
        """
        Submits login request to userservice and saves resulting token

        Fails if userservice does not accept input username and password
        """
        return _login_helper(request.form['username'],
                             request.form['password'])

    def _login_helper(username, password):
        try:
            app.logger.debug('Logging in.')
            req = requests.get(url=app.config["LOGIN_URI"],
                               params={
                                   'username': username,
                                   'password': password
                               })
            req.raise_for_status()  # Raise on HTTP Status code 4XX or 5XX

            # login success
            token = req.json()['token'].encode('utf-8')
            claims = jwt.decode(token, verify=False)
            max_age = claims['exp'] - claims['iat']
            resp = make_response(
                redirect(
                    url_for('home',
                            _external=True,
                            _scheme=app.config['SCHEME'])))
            resp.set_cookie(app.config['TOKEN_NAME'], token, max_age=max_age)
            app.logger.info('Successfully logged in.')
            return resp
        except (RequestException, HTTPError) as err:
            app.logger.error('Error logging in: %s', str(err))
        return redirect(
            url_for('login',
                    msg='Login Failed',
                    _external=True,
                    _scheme=app.config['SCHEME']))

    @app.route("/signup", methods=['GET'])
    def signup_page():
        """
        Renders signup page. Redirects to /login if token is not valid
        """
        token = request.cookies.get(app.config['TOKEN_NAME'])
        if verify_token(token):
            # already authenticated
            app.logger.debug(
                'User already authenticated. Redirecting to /home')
            return redirect(
                url_for('home', _external=True, _scheme=app.config['SCHEME']))
        return render_template('signup.html',
                               cymbal_logo=os.getenv('CYMBAL_LOGO', 'false'),
                               bank_name=os.getenv('BANK_NAME',
                                                   'Bank of Anthos'))

    @app.route("/signup", methods=['POST'])
    def signup():
        """
        Submits signup request to userservice

        Fails if userservice does not accept input form data
        """
        try:
            # create user
            app.logger.debug('Creating new user.')
            resp = requests.post(url=app.config["USERSERVICE_URI"],
                                 data=request.form,
                                 timeout=app.config['BACKEND_TIMEOUT'])
            if resp.status_code == 201:
                # user created. Attempt login
                app.logger.info('New user created.')
                return _login_helper(request.form['username'],
                                     request.form['password'])
        except requests.exceptions.RequestException as err:
            app.logger.error('Error creating new user: %s', str(err))
        return redirect(
            url_for('login',
                    msg='Error: Account creation failed',
                    _external=True,
                    _scheme=app.config['SCHEME']))

    @app.route('/logout', methods=['POST'])
    def logout():
        """
        Logs out user by deleting token cookie and redirecting to login page
        """
        app.logger.info('Logging out.')
        resp = make_response(
            redirect(
                url_for('login_page',
                        _external=True,
                        _scheme=app.config['SCHEME'])))
        resp.delete_cookie(app.config['TOKEN_NAME'])
        return resp

    def verify_token(token):
        """
        Validates token using userservice public key
        """
        app.logger.debug('Verifying token.')
        if token is None:
            return False
        try:
            jwt.decode(token,
                       key=app.config['PUBLIC_KEY'],
                       algorithms='RS256',
                       verify=True)
            app.logger.debug('Token verified.')
            return True
        except jwt.exceptions.InvalidTokenError as err:
            app.logger.error('Error validating token: %s', str(err))
            return False

    # register html template formatters
    def format_timestamp_day(timestamp):
        """ Format the input timestamp day in a human readable way """
        # TODO: time zones?
        date = datetime.datetime.strptime(timestamp,
                                          app.config['TIMESTAMP_FORMAT'])
        return date.strftime('%d')

    def format_timestamp_month(timestamp):
        """ Format the input timestamp month in a human readable way """
        # TODO: time zones?
        date = datetime.datetime.strptime(timestamp,
                                          app.config['TIMESTAMP_FORMAT'])
        return date.strftime('%b')

    def format_currency(int_amount):
        """ Format the input currency in a human readable way """
        if int_amount is None:
            return '$---'
        amount_str = '${:0,.2f}'.format(abs(Decimal(int_amount) / 100))
        if int_amount < 0:
            amount_str = '-' + amount_str
        return amount_str

    # set up global variables
    app.config["TRANSACTIONS_URI"] = 'http://{}/transactions'.format(
        os.environ.get('TRANSACTIONS_API_ADDR'))
    app.config["USERSERVICE_URI"] = 'http://{}/users'.format(
        os.environ.get('USERSERVICE_API_ADDR'))
    app.config["BALANCES_URI"] = 'http://{}/balances'.format(
        os.environ.get('BALANCES_API_ADDR'))
    app.config["HISTORY_URI"] = 'http://{}/transactions'.format(
        os.environ.get('HISTORY_API_ADDR'))
    app.config["LOGIN_URI"] = 'http://{}/login'.format(
        os.environ.get('USERSERVICE_API_ADDR'))
    app.config["CONTACTS_URI"] = 'http://{}/contacts'.format(
        os.environ.get('CONTACTS_API_ADDR'))
    app.config['PUBLIC_KEY'] = open(os.environ.get('PUB_KEY_PATH'), 'r').read()
    app.config['LOCAL_ROUTING'] = os.getenv('LOCAL_ROUTING_NUM')
    app.config[
        'BACKEND_TIMEOUT'] = 4  # timeout in seconds for calls to the backend
    app.config['TOKEN_NAME'] = 'token'
    app.config['TIMESTAMP_FORMAT'] = '%Y-%m-%dT%H:%M:%S.%f%z'
    app.config['SCHEME'] = os.environ.get('SCHEME', 'http')

    # register formater functions
    app.jinja_env.globals.update(format_currency=format_currency)
    app.jinja_env.globals.update(format_timestamp_month=format_timestamp_month)
    app.jinja_env.globals.update(format_timestamp_day=format_timestamp_day)

    # Set up logging
    app.logger.handlers = logging.getLogger('gunicorn.error').handlers
    app.logger.setLevel(logging.getLogger('gunicorn.error').level)
    app.logger.info('Starting frontend service.')

    # Set up tracing and export spans to Cloud Trace.
    if os.environ['ENABLE_TRACING'] == "true":
        app.logger.info("✅ Tracing enabled.")
        trace.set_tracer_provider(TracerProvider())
        cloud_trace_exporter = CloudTraceSpanExporter()
        trace.get_tracer_provider().add_span_processor(
            BatchExportSpanProcessor(cloud_trace_exporter))
        set_global_textmap(CloudTraceFormatPropagator())
        # Add tracing auto-instrumentation for Flask, jinja and requests
        FlaskInstrumentor().instrument_app(app)
        RequestsInstrumentor().instrument()
        Jinja2Instrumentor().instrument()
    else:
        app.logger.info("🚫 Tracing disabled.")

    return app
Example #20
0
@app.route('/book/<username>')
def hello_world(username):
    status = requests.post(os.getenv("BOOK_SVC"),
                           json={
                               "card":
                               "VISA",
                               "name":
                               username,
                               "date":
                               datetime.datetime.today().strftime('%Y-%m-%d')
                           })
    if status.ok:
        resp = status.json()
        return resp
    else:
        return 'bad request!', 400


if __name__ == '__main__':
    endpoint = "{}:{}".format(os.getenv("OTC_HOST"),
                              os.getenv("OTC_PORT", "55680"))
    print('OTC Collector endpoint set to {}'.format(endpoint))

    trace.set_tracer_provider(
        TracerProvider(resource=Resource({"service.name": "api"})))
    trace.get_tracer_provider().add_span_processor(
        BatchExportSpanProcessor(
            OTLPSpanExporter(endpoint=endpoint, insecure=True)))

    app.run(debug=True, host='0.0.0.0')
if __name__ == '__main__':

    OTLPExporter(ExporterType.SPAN)
    exit(0)
    # file = _load_credential_from_file("/root/service.pem")
    # a = 1
    # exit(0)
    # channel = insecure_channel("host.docker.internal:55680")

    trace.set_tracer_provider(TracerProvider())
    trace.get_tracer_provider().add_span_processor(
        BatchExportSpanProcessor(
            OTLPSpanExporter(
                "host.docker.internal:55680",
                # insecure=True,
                # compression=Compression.NONE,
                # headers="rob=testing",
                cert_file="/root/service.pem"))
        #
        # BatchExportSpanProcessor(
        #     OTLPSpanExporter(
        #         protocol=Protocol.HTTP_PROTOBUF,
        #         endpoint="https://host.docker.internal:55681/v1/traces",
        #         insecure=False,
        #         cert_file="/root/ca.crt",
        #         compression=Compression.DEFLATE,
        #     )
        # )
    )
Example #22
0
# See the License for the specific language governing permissions and
# limitations under the License.

from opentelemetry import trace
from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor
from opentelemetry.trace import Link

trace.set_tracer_provider(TracerProvider())

cloud_trace_exporter = CloudTraceSpanExporter()
trace.get_tracer_provider().add_span_processor(
    # BatchExportSpanProcessor buffers spans and sends them in batches in a
    # background thread.
    BatchExportSpanProcessor(cloud_trace_exporter)
)
tracer = trace.get_tracer(__name__)

# Adding attributes to spans
with tracer.start_as_current_span("foo_with_attribute") as current_span:
    current_span.set_attribute("string_attribute", "str")
    current_span.set_attribute("bool_attribute", False)
    current_span.set_attribute("int_attribute", 3)
    current_span.set_attribute("float_attribute", 3.14)

# Adding events to spans
with tracer.start_as_current_span("foo_with_event") as current_span:
    current_span.add_event(name="event_name",)

# Adding links to spans
from opentelemetry.exporter.otlp.metrics_exporter import OTLPMetricsExporter
from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export.controller import PushController
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor

span_exporter = OTLPSpanExporter(
    # optional
    # endpoint:="myCollectorURL:55678",
    # credentials=ChannelCredentials(credentials),
    # metadata=(("metadata", "metadata")),
)
tracer_provider = TracerProvider()
trace.set_tracer_provider(tracer_provider)
span_processor = BatchExportSpanProcessor(span_exporter)
tracer_provider.add_span_processor(span_processor)

metric_exporter = OTLPMetricsExporter(
    # optional
    # endpoint:="myCollectorURL:55678",
    # credentials=ChannelCredentials(credentials),
    # metadata=(("metadata", "metadata")),
)

# Meter is responsible for creating and recording metrics
metrics.set_meter_provider(MeterProvider())
meter = metrics.get_meter(__name__)
# controller collects metrics created from meter and exports it via the
# exporter every interval
controller = PushController(meter, metric_exporter, 5)
Example #24
0
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor
from opentelemetry.ext.requests import RequestsInstrumentor
import time
import random
import socket
import os
import requests

# Setup distributed tracing
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)

trace_exporter = AzureMonitorSpanExporter(
    instrumentation_key=os.environ['APPINSIGHTS_INSTRUMENTATION_KEY'])

span_processor = BatchExportSpanProcessor(trace_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

RequestsInstrumentor().instrument()

# Setup metrics
metrics_exporter = AzureMonitorMetricsExporter(
    instrumentation_key=os.environ['APPINSIGHTS_INSTRUMENTATION_KEY'])
metrics.set_meter_provider(MeterProvider())
meter = metrics.get_meter(__name__)
PushController(meter, metrics_exporter, 10)

tfgen_counter = meter.create_metric(
    name="tfgen_counter",
    description="mydemo namespace",
    unit="1",
Example #25
0
def create_app():
    """Flask application factory to create instances
    of the Contact Service Flask App
    """
    app = Flask(__name__)


    # Disabling unused-variable for lines with route decorated functions
    # as pylint thinks they are unused
    # pylint: disable=unused-variable
    @app.route("/version", methods=["GET"])
    def version():
        """
        Service version endpoint
        """
        return app.config["VERSION"], 200

    @app.route("/ready", methods=["GET"])
    def ready():
        """Readiness probe."""
        return "ok", 200

    @app.route("/contacts/<username>", methods=["GET"])
    def get_contacts(username):
        """Retrieve the contacts list for the authenticated user.
        This list is used for populating Payment and Deposit fields.

        Return: a list of contacts
        """
        auth_header = request.headers.get("Authorization")
        if auth_header:
            token = auth_header.split(" ")[-1]
        else:
            token = ""
        try:
            auth_payload = jwt.decode(
                token, key=app.config["PUBLIC_KEY"], algorithms="RS256"
            )
            if username != auth_payload["user"]:
                raise PermissionError

            contacts_list = contacts_db.get_contacts(username)
            app.logger.debug("Succesfully retrieved contacts.")
            return jsonify(contacts_list), 200
        except (PermissionError, jwt.exceptions.InvalidTokenError) as err:
            app.logger.error("Error retrieving contacts list: %s", str(err))
            return "authentication denied", 401
        except SQLAlchemyError as err:
            app.logger.error("Error retrieving contacts list: %s", str(err))
            return "failed to retrieve contacts list", 500

    @app.route("/contacts/<username>", methods=["POST"])
    def add_contact(username):
        """Add a new favorite account to user's contacts list

        Fails if account or routing number are invalid
        or if label is not alphanumeric

        request fields:
        - account_num
        - routing_num
        - label
        - is_external
        """
        auth_header = request.headers.get("Authorization")
        if auth_header:
            token = auth_header.split(" ")[-1]
        else:
            token = ""
        try:
            auth_payload = jwt.decode(
                token, key=app.config["PUBLIC_KEY"], algorithms="RS256"
            )
            if username != auth_payload["user"]:
                raise PermissionError
            req = {
                k: (bleach.clean(v) if isinstance(v, str) else v)
                for k, v in request.get_json().items()
            }
            _validate_new_contact(req)

            _check_contact_allowed(username, auth_payload["acct"], req)
            # Create contact data to be added to the database.
            contact_data = {
                "username": username,
                "label": req["label"],
                "account_num": req["account_num"],
                "routing_num": req["routing_num"],
                "is_external": req["is_external"],
            }
            # Add contact_data to database
            app.logger.debug("Adding new contact to the database.")
            contacts_db.add_contact(contact_data)
            app.logger.info("Successfully added new contact.")
            return jsonify({}), 201

        except (PermissionError, jwt.exceptions.InvalidTokenError) as err:
            app.logger.error("Error adding contact: %s", str(err))
            return "authentication denied", 401
        except UserWarning as warn:
            app.logger.error("Error adding contact: %s", str(warn))
            return str(warn), 400
        except ValueError as err:
            app.logger.error("Error adding contact: %s", str(err))
            return str(err), 409
        except SQLAlchemyError as err:
            app.logger.error("Error adding contact: %s", str(err))
            return "failed to add contact", 500

    def _validate_new_contact(req):
        """Check that this new contact request has valid fields"""
        app.logger.debug("validating add contact request: %s", str(req))
        # Check if required fields are filled
        fields = ("label", "account_num", "routing_num", "is_external")
        if any(f not in req for f in fields):
            raise UserWarning("missing required field(s)")

        # Validate account number (must be 10 digits)
        if req["account_num"] is None or not re.match(r"\A[0-9]{10}\Z", req["account_num"]):
            raise UserWarning("invalid account number")
        # Validate routing number (must be 9 digits)
        if req["routing_num"] is None or not re.match(r"\A[0-9]{9}\Z", req["routing_num"]):
            raise UserWarning("invalid routing number")
        # Only allow external accounts to deposit
        if (req["is_external"] and req["routing_num"] == app.config["LOCAL_ROUTING"]):
            raise UserWarning("invalid routing number")
        # Validate label
        # Must be >0 and <=30 chars, alphanumeric and spaces, can't start with space
        if req["label"] is None or not re.match(r"^[0-9a-zA-Z][0-9a-zA-Z ]{0,29}$", req["label"]):
            raise UserWarning("invalid account label")

    def _check_contact_allowed(username, accountid, req):
        """Check that this contact is allowed to be created"""
        app.logger.debug("checking that this contact is allowed to be created: %s", str(req))
        # Don't allow self reference
        if (req["account_num"] == accountid and req["routing_num"] == app.config["LOCAL_ROUTING"]):
            raise ValueError("may not add yourself to contacts")

        # Don't allow identical contacts
        for contact in contacts_db.get_contacts(username):
            if (contact["account_num"] == req["account_num"]
                    and contact["routing_num"] == req["routing_num"]):
                raise ValueError("account already exists as a contact")

            if contact["label"] == req["label"]:
                raise ValueError("contact already exists with that label")

    @atexit.register
    def _shutdown():
        """Executed when web app is terminated."""
        app.logger.info("Stopping contacts service.")

    # set log formatting
    date_format = "%Y-%m-%d %H:%M:%S"
    message_format = '%(asctime)s | [%(levelname)s] | %(funcName)s | %(message)s'
    logging.basicConfig(format= message_format, datefmt= date_format, stream=sys.stdout)

    # set log level
    log_levels = {
        "DEBUG": logging.DEBUG,
        "WARNING": logging.WARNING,
        "INFO": logging.INFO,
        "ERROR": logging.ERROR,
        "CRITICAL": logging.CRITICAL
    }
    level = logging.INFO #default
    user_log_level = os.environ.get("LOG_LEVEL")
    if user_log_level is not None and user_log_level.upper() in log_levels:
        level = log_levels.get(user_log_level.upper())
    app.logger.setLevel(level)
    app.logger.info("Starting contacts service.")

    # Set up tracing and export spans to Cloud Trace.
    if os.environ['ENABLE_TRACING'] == "true":
        app.logger.info("✅ Tracing enabled.")
        # Set up tracing and export spans to Cloud Trace
        trace.set_tracer_provider(TracerProvider())
        cloud_trace_exporter = CloudTraceSpanExporter()
        trace.get_tracer_provider().add_span_processor(
            BatchExportSpanProcessor(cloud_trace_exporter)
        )
        set_global_textmap(CloudTraceFormatPropagator())
        FlaskInstrumentor().instrument_app(app)
    else:
        app.logger.info("🚫 Tracing disabled.")


    # setup global variables
    app.config["VERSION"] = os.environ.get("VERSION")
    app.config["LOCAL_ROUTING"] = os.environ.get("LOCAL_ROUTING_NUM")
    app.config["PUBLIC_KEY"] = open(os.environ.get("PUB_KEY_PATH"), "r").read()

    # Configure database connection
    try:
        contacts_db = ContactsDb(os.environ.get("ACCOUNTS_DB_URI"), app.logger)
    except OperationalError:
        app.logger.critical("database connection failed")
        sys.exit(1)
    return app
Example #26
0
from opentelemetry.ext import http_requests
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor
from opentelemetry.ext.wsgi import OpenTelemetryMiddleware


# configure tracer and exporter
ot_exporter = CollectorSpanExporter(
    service_name="py-service",
    endpoint="localhost:55678",
)

provider = TracerProvider()
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
provider.add_span_processor(BatchExportSpanProcessor(ot_exporter))

# instrument http client
http_requests.enable(provider)

# create and instrument flask server
app = Flask(__name__)
app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app)


@app.route("/")
def hello():
    with tracer.start_as_current_span("fetch-from-node"):
        response = fetch_from_node()
        return "hello from python\n" + response
Example #27
0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# jaeger_example.py
from opentelemetry import trace
from opentelemetry.ext import jaeger
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor

trace.set_tracer_provider(TracerProvider())

jaeger_exporter = jaeger.JaegerSpanExporter(
    service_name="my-helloworld-service",
    agent_host_name="localhost",
    agent_port=6831,
)

trace.get_tracer_provider().add_span_processor(
    BatchExportSpanProcessor(jaeger_exporter))

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("foo"):
    with tracer.start_as_current_span("bar"):
        with tracer.start_as_current_span("baz"):
            print("Hello world from OpenTelemetry Python!")
from azure.core.settings import settings
from azure.core.tracing.ext.opentelemetry_span import OpenTelemetrySpan

settings.tracing_implementation = OpenTelemetrySpan

# Regular open telemetry usage from here, see https://github.com/open-telemetry/opentelemetry-python
# for details
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)

# azure monitor trace exporter to send telemetry to appinsights
from azure.opentelemetry.exporter.azuremonitor import AzureMonitorTraceExporter
span_processor = BatchExportSpanProcessor(
    AzureMonitorTraceExporter(
        connection_string=os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
trace.get_tracer_provider().add_span_processor(span_processor)

# Example with Servicebus SDKs
from azure.storage.blob import BlobServiceClient

connection_string = os.environ['AZURE_STORAGE_CONNECTION_STRING']
container_name = os.environ['AZURE_STORAGE_BLOB_CONTAINER_NAME']

with tracer.start_as_current_span(name="MyStorageApplication"):
    client = BlobServiceClient.from_connection_string(connection_string)
    client.create_container(container_name)  # Call will be traced
Example #29
0
async def fetch(session: aiohttp.ClientSession, url, payload):
    async with session.post(url, data=payload) as resp:
        return await resp.json()


async def make_booking(request):
    async with aiohttp.ClientSession() as session:
        results = await asyncio.gather(
            fetch(session,
                  os.getenv("PAY_SVC"),
                  payload={"card": request.json["card"]}),
            fetch(session,
                  os.getenv("RSV_SVC"),
                  payload={
                      "date": request.json["date"],
                      "name": request.json["name"]
                  }))

    print(results)
    return web.Response(body="success!", status=200)


app = web.Application()
app.add_routes([web.get('/booking', make_booking)])

if __name__ == '__main__':
    trace.set_tracer_provider(
        TracerProvider(resource=Resource({"service.name": "booking"})))
    trace.get_tracer_provider().add_span_processor(
        BatchExportSpanProcessor(OTLPSpanExporter(os.getenv("OTC_HOST"))))
    web.run_app(app, port=5000)
Example #30
0
from opentelemetry import trace
from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    BatchExportSpanProcessor,
    ConsoleSpanExporter,
    SimpleExportSpanProcessor,
)

# Set up OpenTelemetry tracing
trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
    SimpleExportSpanProcessor(ConsoleSpanExporter()))
trace.get_tracer_provider().add_span_processor(
    BatchExportSpanProcessor(CloudTraceSpanExporter(),
                             schedule_delay_millis=5000))

# Trace postgres queries as well
Psycopg2Instrumentor().instrument()

import psycopg2
from google.cloud.sqlcommenter.psycopg2.extension import CommenterCursorFactory

tracer = trace.get_tracer(__name__)


def main():
    cursor_factory = CommenterCursorFactory(
        with_db_driver=True,
        with_dbapi_level=True,
        with_dbapi_threadsafety=True,