class Model(BaseModel): # hacking for type annotation ... else: Model = db.Model tracer = trace.get_tracer(__name__) # pytest no need to check if not setting.ENV == "TEST": use_console_exporter = True if use_console_exporter: span_processor = BatchSpanProcessor(ConsoleSpanExporter()) else: jaeger_exporter = JaegerExporter( agent_host_name="jaeger", agent_port=6831, ) span_processor = BatchSpanProcessor(jaeger_exporter) trace.set_tracer_provider( TracerProvider(resource=Resource.create({SERVICE_NAME: "tifa"}))) provider = trace.get_tracer_provider() provider.add_span_processor(span_processor) celery = Celery() celery.conf.broker_url = setting.REDIS_CELERY_URL celery.conf.timezone = "Asia/Shanghai"
import time from opentelemetry import trace from opentelemetry.ext import jaeger from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchExportSpanProcessor trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) tracer = trace.get_tracer(__name__) # create a JaegerSpanExporter jaeger_exporter = jaeger.JaegerSpanExporter( service_name="my-helloworld-service", # configure agent agent_host_name="localhost", 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 factory trace.tracer_provider().add_span_processor(span_processor) # create some spans for testing
from flask import jsonify, Flask, request import os import argparse from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider, Resource from opentelemetry.sdk.trace.export import BatchExportSpanProcessor from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter app = Flask("payments") @app.route("/process", methods=["POST"]) def process_card(): return jsonify({"status": "charged {} $abc".format(request.json["card"])}) if __name__ == '__main__': trace.set_tracer_provider( TracerProvider(resource=Resource({"service.name": "payments"}))) trace.get_tracer_provider().add_span_processor( BatchExportSpanProcessor(OTLPSpanExporter(os.getenv("OTC_HOST")))) app.run(debug=True, host='0.0.0.0')
elif 'btn-nclicks-4' in changed_id: return deliveryStatus() + old_output elif 'btn-nclicks-5' in changed_id: return payOrder() + old_output else: load_main_screen() return old_output trace.set_tracer_provider( TracerProvider(resource=Resource.create({ "service.name": "frontend-client", "host.hostname": socket.gethostname(), "telemetry.sdk.name": "opentelemetry", "telemetry.sdk.language": "python", "telemetry.sdk.version": pkg_resources.get_distribution("opentelemetry-sdk").version, }))) tracerProvider = trace.get_tracer_provider() tracer = tracerProvider.get_tracer(__name__) tracerProvider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter())) otlp_exporter = OTLPSpanExporter(endpoint="{}:55680".format(OTLP), insecure=True) tracerProvider.add_span_processor(SimpleSpanProcessor(otlp_exporter)) RequestsInstrumentor().instrument(tracer_provider=tracerProvider) retry_strategy = Retry(total=2,
app = Flask(__name__) OTLP = os.getenv("OTLP") if os.getenv("OTLP") is not None else "localhost" INVENTORY = os.getenv("INVENTORY") if os.getenv( "INVENTORY") is not None else "localhost" LOGS = os.getenv("LOGS") if os.getenv("LOGS") is not None else "localhost" trace.set_tracer_provider( TracerProvider(resource=Resource.create({ "service.name": "payment", "service.instance.id": str(id(app)), "telemetry.sdk.name": "opentelemetry", "telemetry.sdk.language": "python", "telemetry.sdk.version": pkg_resources.get_distribution("opentelemetry-sdk").version, "host.hostname": socket.gethostname(), }))) tracerProvider = trace.get_tracer_provider() tracer = tracerProvider.get_tracer(__name__) tracerProvider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter())) otlp_exporter = OTLPSpanExporter(endpoint="{}:55680".format(OTLP), insecure=True) tracerProvider.add_span_processor(SimpleSpanProcessor(otlp_exporter)) FlaskInstrumentor().instrument_app(app)
import os import requests from flask import Flask from opentelemetry import trace from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry.instrumentation.requests import RequestsInstrumentor from opentelemetry.exporter.jaeger.thrift import JaegerExporter exporter = ConsoleSpanExporter() resource = Resource.create({"service.name": "grocery-store"}) provider = TracerProvider(resource=resource) span_processor = BatchSpanProcessor(exporter) provider.add_span_processor(span_processor) provider.add_span_processor(BatchSpanProcessor(JaegerExporter())) trace.set_tracer_provider(provider) app = Flask(__name__) FlaskInstrumentor().instrument_app(app) RequestsInstrumentor().instrument() @app.route("/") def welcome(): with trace.get_tracer(__name__).start_as_current_span("welcome message"): return "Welcome to the grocery store!"
ConsoleSpanExporter, SimpleSpanProcessor, BatchSpanProcessor, ) from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry.instrumentation.requests import RequestsInstrumentor from prometheus_client import start_http_server, Counter service_name = os.environ.get('SERVICE_NAME', 'otel-flask-service') agent_host = os.environ.get('AGENT_HOST', 'localhost') agent_port = os.environ.get('AGENT_PORT', '6831') trace.set_tracer_provider( TracerProvider( resource=Resource.create({SERVICE_NAME: service_name}) ) ) jaeger_exporter = JaegerExporter( agent_host_name = agent_host, agent_port = int(agent_port), ) trace.get_tracer_provider().add_span_processor( BatchSpanProcessor(jaeger_exporter) ) # Create a metric to track total number of requests made. REQUEST_TOTAL = Counter('total_requests', 'Total number of HTTP requests')
import datetime import requests import uuid import os from opentelemetry import trace from opentelemetry.sdk.trace import Resource, TracerProvider from opentelemetry.sdk.trace.export import BatchExportSpanProcessor from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter app = Flask("api") @app.route('/echo', methods=["POST"]) def echo_route(): return jsonify({"message": "Hello from Echo Service!"}) 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": "echo"}))) trace.get_tracer_provider().add_span_processor( BatchExportSpanProcessor( OTLPSpanExporter(endpoint=endpoint, insecure=True))) app.run(debug=True, host='0.0.0.0')
def enable_tracing() -> None: from opentelemetry.trace import set_tracer_provider from opentelemetry.sdk.trace import TracerProvider from opentelemetry.trace.sampling import DEFAULT_OFF set_tracer_provider(TracerProvider(sampler=DEFAULT_OFF))
def setUp(self): tracer_provider = TracerProvider() self.exporter = OTLPSpanExporter(insecure=True) tracer_provider.add_span_processor(SimpleSpanProcessor(self.exporter)) self.tracer = tracer_provider.get_tracer(__name__) self.server = server(ThreadPoolExecutor(max_workers=10)) self.server.add_insecure_port("[::]:4317") self.server.start() event_mock = Mock( **{ "timestamp": 1591240820506462784, "attributes": BoundedAttributes( attributes={"a": 1, "b": False} ), } ) type(event_mock).name = PropertyMock(return_value="a") self.span = _Span( "a", context=Mock( **{ "trace_state": OrderedDict([("a", "b"), ("c", "d")]), "span_id": 10217189687419569865, "trace_id": 67545097771067222548457157018666467027, } ), resource=SDKResource(OrderedDict([("a", 1), ("b", False)])), parent=Mock(**{"span_id": 12345}), attributes=BoundedAttributes(attributes={"a": 1, "b": True}), events=[event_mock], links=[ Mock( **{ "context.trace_id": 1, "context.span_id": 2, "attributes": BoundedAttributes( attributes={"a": 1, "b": False} ), "kind": OTLPSpan.SpanKind.SPAN_KIND_INTERNAL, # pylint: disable=no-member } ) ], instrumentation_info=InstrumentationInfo( name="name", version="version" ), ) self.span2 = _Span( "b", context=Mock( **{ "trace_state": OrderedDict([("a", "b"), ("c", "d")]), "span_id": 10217189687419569865, "trace_id": 67545097771067222548457157018666467027, } ), resource=SDKResource(OrderedDict([("a", 2), ("b", False)])), parent=Mock(**{"span_id": 12345}), instrumentation_info=InstrumentationInfo( name="name", version="version" ), ) self.span3 = _Span( "c", context=Mock( **{ "trace_state": OrderedDict([("a", "b"), ("c", "d")]), "span_id": 10217189687419569865, "trace_id": 67545097771067222548457157018666467027, } ), resource=SDKResource(OrderedDict([("a", 1), ("b", False)])), parent=Mock(**{"span_id": 12345}), instrumentation_info=InstrumentationInfo( name="name2", version="version2" ), ) self.span.start() self.span.end() self.span2.start() self.span2.end() self.span3.start() self.span3.end()
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('/whereami', methods=['GET']) def whereami(): """ Returns the cluster name + zone name where this Pod is running. """ return "Cluster: " + cluster_name + ", Pod: " + pod_name + ", Zone: " + pod_zone, 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', cluster_name=cluster_name, pod_name=pod_name, pod_zone=pod_zone, 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 as http_request_err: raise UserWarning(resp.text) from http_request_err 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 as http_request_err: raise UserWarning(resp.text) from http_request_err @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'), cluster_name=cluster_name, pod_name=pod_name, pod_zone=pod_zone, 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'), cluster_name=cluster_name, pod_name=pod_name, pod_zone=pod_zone, 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') # where am I? metadata_url = 'http://metadata.google.internal/computeMetadata/v1/' metadata_headers = {'Metadata-Flavor': 'Google'} # get GKE cluster name cluster_name = "unknown" try: req = requests.get(metadata_url + 'instance/attributes/cluster-name', headers=metadata_headers) if req.ok: cluster_name = str(req.text) except (RequestException, HTTPError) as err: app.logger.warning("Unable to capture GKE cluster name.") # get GKE pod name pod_name = "unknown" pod_name = socket.gethostname() # get GKE node zone pod_zone = "unknown" try: req = requests.get(metadata_url + 'instance/zone', headers=metadata_headers) if req.ok: pod_zone = str(req.text.split("/")[3]) except (RequestException, HTTPError) as err: app.logger.warning("Unable to capture GKE node zone.") # 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
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 up logger app.logger.handlers = logging.getLogger("gunicorn.error").handlers app.logger.setLevel(logging.getLogger("gunicorn.error").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
def create_app(): """Flask application factory to create instances of the Connector Service Flask App """ app = Flask(__name__) # 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( SimpleExportSpanProcessor(cloud_trace_exporter)) set_global_httptextformat(CloudTraceFormatPropagator()) # Add Flask auto-instrumentation for tracing FlaskInstrumentor().instrument_app(app) # 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("/sync", methods=["POST"]) def sync(): """Sync PostgreSQL metadata with Google Data Catalog """ 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 auth_payload is None: raise PermissionError logging.info("Starting sync logic.") datacatalog_cli.PostgreSQL2DatacatalogCli().run( _get_connector_run_args()) logging.info("Sync execution done.") return jsonify({}), 200 except (PermissionError, jwt.exceptions.InvalidTokenError) as err: logging.error("Error executing sync: %s", str(err)) return "authentication denied", 401 except UserWarning as warn: logging.error("Error executing sync: %s", str(warn)) return str(warn), 400 except Exception as err: logging.error("Error executing sync: %s", str(err)) return "failed to sync", 500 @atexit.register def _shutdown(): """Executed when web app is terminated.""" logging.info("Stopping contacts service.") def _get_connector_run_args(): return [ '--datacatalog-project-id', os.environ.get('DATACATALOG_PROJECT_ID'), '--datacatalog-location-id', os.environ.get('DATACATALOG_LOCATION_ID'), '--postgresql-host', os.environ.get('POSTGRESQL_SERVER'), '--postgresql-user', os.environ.get('POSTGRES_USER'), '--postgresql-pas', os.environ.get('POSTGRES_PASSWORD'), '--postgresql-database', os.environ.get('POSTGRES_DB') ] logging_client = gcp_logging.Client() logging_client.setup_logging(log_level=logging.INFO) root_logger = logging.getLogger() # use the GCP handler ONLY in order to prevent logs from getting written to STDERR root_logger.handlers = [ handler for handler in root_logger.handlers if isinstance(handler, (CloudLoggingHandler, ContainerEngineHandler, AppEngineHandler)) ] logging.info("Service PostgreSQL connector created.") # setup global variables app.config["VERSION"] = os.environ.get("VERSION") app.config["PUBLIC_KEY"] = open(os.environ.get("PUB_KEY_PATH"), "r").read() return app
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor from opentelemetry.instrumentation.requests import RequestsInstrumentor from opentelemetry.sdk.resources import SERVICE_NAME, Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter app = Flask(__name__) app.config.from_object(Config) db = SQLAlchemy(app) # Set global TracerProvider before instrumenting trace.set_tracer_provider( TracerProvider(resource=Resource.create({SERVICE_NAME: "flask-sample"}))) # Enable tracing for sqlalchemy library SQLAlchemyInstrumentor().instrument() # Enable tracing for Flask library FlaskInstrumentor().instrument_app(app) # Enable tracing for requests library RequestsInstrumentor().instrument() trace_exporter = AzureMonitorTraceExporter( connection_string=Config.CONNECTION_STRING) trace.get_tracer_provider().add_span_processor( BatchSpanProcessor(trace_exporter))
def setUp(self): """Create an OpenTelemetry tracer and a shim before every test case.""" trace.set_tracer_provider(TracerProvider()) self.shim = create_tracer(trace.get_tracer_provider())
def setUpClass(cls): set_tracer_provider(TracerProvider())
rsv_status = requests.post(os.getenv("RSV_SVC"), json={ "date": request.json["date"], "name": request.json["name"] }) if not rsv_status.ok: return 'bad request for rsv', 400 return jsonify({ "payment": pay_status.json(), "reservation": rsv_status.json() }) @app.route("/debug", methods=["POST"]) def make_debug(): return jsonify(request.json) 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": "booking"}))) trace.get_tracer_provider().add_span_processor( BatchExportSpanProcessor( OTLPSpanExporter(endpoint=endpoint, insecure=True))) app.run(debug=True, host='0.0.0.0')
from flask import jsonify, Flask, request import os from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider, Resource from opentelemetry.sdk.trace.export import BatchExportSpanProcessor from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter app = Flask("reservations") @app.route("/reserve", methods=["POST"]) def reserve(): return jsonify({"status": "reserved for {} {}".format(request.json['name'], request.json['date'])}) 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": "reservations"}))) trace.get_tracer_provider().add_span_processor(BatchExportSpanProcessor(OTLPSpanExporter(endpoint=endpoint, insecure=True))) app.run(debug=True, host='0.0.0.0')
# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.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. from opentelemetry import trace from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( ConsoleSpanExporter, SimpleSpanProcessor, ) resource = Resource.create({"service.name": "basic_service"}) trace.set_tracer_provider(TracerProvider(resource=resource)) trace.get_tracer_provider().add_span_processor( SimpleSpanProcessor(ConsoleSpanExporter())) tracer = trace.get_tracer(__name__) with tracer.start_as_current_span("foo"): print("Hello world!")
def setUpClass(cls): trace.set_tracer_provider( TracerProvider( resource=Resource({SERVICE_NAME: TEST_SERVICE_NAME})))
from opentelemetry.sdk.trace import TracerProvider, sampling from opentelemetry.sdk.trace.export import SimpleSpanProcessor TEST_DURATION_SECONDS = 15 SPANS_PER_SECOND = 10_000 class MockTraceServiceStub(object): def __init__(self, channel): self.Export = lambda *args, **kwargs: None old_stub = OTLPSpanExporter._stub OTLPSpanExporter._stub = MockTraceServiceStub simple_span_processor = SimpleSpanProcessor(OTLPSpanExporter()) tracer = TracerProvider( active_span_processor=simple_span_processor, sampler=sampling.DEFAULT_ON, ).get_tracer("resource_usage_tracer") starttime = time.time() for _ in range(TEST_DURATION_SECONDS): for _ in range(SPANS_PER_SECOND): span = tracer.start_span("benchmarkedSpan") span.end() time_to_finish_spans = time.time() - starttime time.sleep(1.0 - time_to_finish_spans if time_to_finish_spans < 1.0 else 0) OTLPSpanExporter._stub = old_stub
def configure_exporter(exporter): trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(exporter)) propagators.set_global_textmap(CloudTraceFormatPropagator())
# Licensed under the MIT License. """ An example to show an application using Opentelemetry tracing api and sdk with the OpenTelemetry Collector and the Azure monitor exporter. Telemetry is exported to application insights with the AzureMonitorTraceExporter and Zipkin with the OTLP Span exporter. """ import os from opentelemetry import trace from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.resources import SERVICE_NAME, Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter trace.set_tracer_provider( TracerProvider( resource=Resource.create({SERVICE_NAME: "my-zipkin-service"}))) tracer = trace.get_tracer(__name__) exporter = AzureMonitorTraceExporter.from_connection_string( os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"]) otlp_exporter = OTLPSpanExporter(endpoint="http://localhost:4317") span_processor = BatchSpanProcessor(otlp_exporter) trace.get_tracer_provider().add_span_processor(span_processor) with tracer.start_as_current_span("test"): print("Hello world!") input(...)
BatchExportSpanProcessor, ) from opentelemetry.resource import AwsLambdaResourceDetector from opentelemetry.instrumentation.aws_lambda import AwsLambdaInstrumentor from pkg_resources import iter_entry_points logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # TODO: get_aggregated_resources resource = Resource.create().merge(AwsLambdaResourceDetector().detect()) trace.set_tracer_provider( TracerProvider( ids_generator=AWSXRayIdsGenerator(), resource=resource, ) ) console_exporter = os.environ.get("CONSOLE_EXPORTER", None) if not console_exporter is None: from opentelemetry.sdk.trace.export import ConsoleSpanExporter trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) ) logger.info("Console exporter initialized.") ci = os.environ.get("CI", None) if ci is None: from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter
# type: ignore """Basic test script using jaeger.""" # fmt:off from opentelemetry import trace from opentelemetry.exporter.jaeger.thrift import JaegerExporter from opentelemetry.sdk.resources import SERVICE_NAME, Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor trace.set_tracer_provider( TracerProvider( resource=Resource.create({SERVICE_NAME: "my-helloworld-service"}))) jaeger_exporter = JaegerExporter( agent_host_name="localhost", agent_port=6831, ) trace.get_tracer_provider().add_span_processor( BatchSpanProcessor(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!")
def configure_opentelemetry( access_token: str = _LS_ACCESS_TOKEN, span_endpoint: str = _OTEL_EXPORTER_OTLP_SPAN_ENDPOINT, metric_endpoint: str = _OTEL_EXPORTER_OTLP_METRIC_ENDPOINT, service_name: str = _LS_SERVICE_NAME, service_version: str = _LS_SERVICE_VERSION, propagator: list = _OTEL_PROPAGATORS, resource_labels: str = _OTEL_RESOURCE_LABELS, log_level: int = _OTEL_LOG_LEVEL, span_exporter_endpoint_insecure: bool = _OTEL_EXPORTER_OTLP_SPAN_INSECURE, metric_exporter_endpoint_insecure: bool = ( _OTEL_EXPORTER_OTLP_METRIC_INSECURE ), ): """ Configures OpenTelemetry with Lightstep environment variables This function works as a configuration layer that allows the Lightstep end user to use current environment variables seamlessly with OpenTelemetry. In this way, it is not needed to make any configuration changes to the environment before using OpenTelemetry. The configuration can be done via environment variables (prefixed with `LS`) or via arguments passed to this function. Each argument has a 1:1 correspondence with an environment variable, their description follows: Arguments: access_token (str): LS_ACCESS_TOKEN, the access token used to authenticate with the Lightstep satellite. This configuration value is mandatory. span_endpoint (str): OTEL_EXPORTER_OTLP_SPAN_ENDPOINT, the URL of the Lightstep satellite where the spans are to be exported. Defaults to `ingest.lightstep.com:443`. metric_endpoint (str): OTEL_EXPORTER_OTLP_METRIC_ENDPOINT, the URL of the metrics collector where the metrics are to be exported. Defaults to `ingest.lightstep.com:443/metrics`. service_name (str): LS_SERVICE_NAME, the name of the service that is used along with the access token to send spans to the Lighstep satellite. This configuration value is mandatory. service_version (str): LS_SERVICE_VERSION, the version of the service used to sernd spans to the Lightstep satellite. Defaults to `"unknown"`. propagator (list): OTEL_PROPAGATORS, a list of propagators to be used. Defaults to `["b3"]`. resource_labels (dict): OTEL_RESOURCE_LABELS, a dictionary of key value pairs used to instantiate the resouce of the tracer provider. Defaults to `{ "service.name": _LS_SERVICE_NAME, "service.version": _LS_SERVICE_VERSION, "telemetry.sdk.language": "python", "telemetry.sdk.version": "0.9b0", }` log_level (int): OTEL_LOG_LEVEL, a boolean value that indicates the log level. Defaults to `logging.DEBUG`. information is to be printed. Defaults to `False`. span_exporter_endpoint_insecure (bool): OTEL_EXPORTER_OTLP_SPAN_INSECURE, a boolean value that indicates if an insecure channel is to be used to send spans to the satellite. Defaults to `False`. metric_exporter_endpoint_insecure (bool): OTEL_EXPORTER_OTLP_METRIC_INSECURE, a boolean value that indicates if an insecure channel is to be used to send spans to the satellite. Defaults to `False`. """ basicConfig(level=log_level) _logger.debug("configuration") for key, value in { "access_token": access_token, "span_endpoint": span_endpoint, "metric_endpoint": metric_endpoint, "service_name": service_name, "service_version": service_version, "propagator": propagator, "resource_labels": resource_labels, "log_level": log_level, "span_exporter_endpoint_insecure": span_exporter_endpoint_insecure, "metric_exporter_endpoint_insecure": metric_exporter_endpoint_insecure, }.items(): _logger.debug("%s: %s", key, value) if not _validate_service_name(service_name): message = ( "Invalid configuration: service name missing. " "Set environment variable LS_SERVICE_NAME or call " "configure_opentelemetry with service_name defined" ) _logger.error(message) raise InvalidConfigurationError(message) if access_token is None: if span_endpoint == _DEFAULT_OTEL_EXPORTER_OTLP_SPAN_ENDPOINT: message = ( "Invalid configuration: token missing. " "Must be set to send data to {}. " "Set environment variable LS_ACCESS_TOKEN or call" "configure_opentelemetry with access_token defined" ).format(_OTEL_EXPORTER_OTLP_SPAN_ENDPOINT) _logger.error(message) raise InvalidConfigurationError(message) if not _validate_token(access_token): message = ( "Invalid configuration: invalid token. " "Token must be a 32, 84 or 104 character long string." ) _logger.error(message) raise InvalidConfigurationError(message) _logger.debug("configuring propagation") # FIXME use entry points (instead of a dictionary) to locate propagator # classes set_global_httptextformat( CompositeHTTPPropagator( [{"b3": B3Format}[propagator] for propagator in _OTEL_PROPAGATORS] ) ) _logger.debug("configuring tracing") metadata = None if _env.str("OPENTELEMETRY_PYTHON_TRACER_PROVIDER", None) is None: # FIXME now that new values can be set in the global configuration # object, check for this object having a tracer_provider attribute, if # not, set it to "sdk_tracer_provider" instead of using # set_tracer_provider, this in order to avoid having more than one # method of setting configuration. set_tracer_provider(TracerProvider()) if access_token != "": metadata = (("lightstep-access-token", access_token),) credentials = ssl_channel_credentials() if span_exporter_endpoint_insecure: credentials = None # FIXME Do the same for metrics when the OTLPMetricsExporter is in # OpenTelemetry. get_tracer_provider().add_span_processor( BatchExportSpanProcessor( LightstepOTLPSpanExporter( endpoint=span_endpoint, credentials=credentials, metadata=metadata, ) ) ) get_tracer_provider().resource = Resource(resource_labels) if log_level == DEBUG: get_tracer_provider().add_span_processor( BatchExportSpanProcessor(ConsoleSpanExporter()) )
SERVICE_NAME: str = "orchestrator-core" LOGGING_HOST: str = "localhost" LOG_LEVEL: str = "DEBUG" SLACK_ENGINE_SETTINGS_HOOK_ENABLED: bool = False SLACK_ENGINE_SETTINGS_HOOK_URL: str = "" TRACING_ENABLED: bool = False TRANSLATIONS_DIR: Optional[Path] = None WEBSOCKET_BROADCASTER_URL: str = "memory://" ENABLE_WEBSOCKETS: bool = True DISABLE_INSYNC_CHECK: bool = False DEFAULT_PRODUCT_WORKFLOWS: List[str] = ["modify_note"] class Oauth2Settings(BaseSettings): OAUTH2_ACTIVE: bool = False OAUTH2_RESOURCE_SERVER_ID: str = "" OAUTH2_RESOURCE_SERVER_SECRET: str = "" OAUTH2_TOKEN_URL: str = "" OIDC_CONF_WELL_KNOWN_URL: str = "" OPA_URL: str = "http://127.0.0.1:8181/v1/data/automation/authorization/allow" app_settings = AppSettings() oauth2_settings = Oauth2Settings() # Tracer settings tracer_provider = TracerProvider() jaeger_exporter = JaegerExporter(agent_host_name=app_settings.LOGGING_HOST, udp_split_oversized_batches=True) tracer_provider.add_span_processor(BatchSpanProcessor(jaeger_exporter))
def tracer(): trace.set_tracer_provider(TracerProvider()) return trace.get_tracer(__name__)
jaeger_exporter = jaeger.JaegerSpanExporter( service_name="my-traced-service", agent_host_name="simplest-agent.observability.svc.cluster.local", agent_port=6831 ) trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(jaeger_exporter) ) app = flask.Flask(__name__) FlaskInstrumentor().instrument_app(app) opentelemetry.ext.requests.RequestsInstrumentor().instrument() ''' #-------------------------------------------------------------- trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) # create a JaegerSpanExporter jaeger_exporter = jaeger.JaegerSpanExporter( service_name="TracedService2", agent_host_name="simplest-agent.observability.svc.cluster.local", # agent_host_name="jaeger-agent.observability.svc.cluster.local", 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 )
from opentelemetry import trace from opentelemetry.exporter.jaeger.thrift import JaegerExporter from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor trace.set_tracer_provider( TracerProvider(resource=Resource.create( {"service.name": "example_exporter"}), ), ) # Configurando o agente do jeager # From https://opentelemetry-python.readthedocs.io/en/latest/exporter/jaeger/jaeger.html jaeger_exporter = JaegerExporter( agent_host_name='jaeger', agent_port=6831, ) # Criando um span e vinculando a um BatchSpanProcessor para envio ao Jeager # https://opentelemetry-python.readthedocs.io/en/stable/sdk/trace.export.html?highlight=BatchSpanProcessor#opentelemetry.sdk.trace.export.BatchSpanProcessor span_processor = BatchSpanProcessor(jaeger_exporter) # Neste exemplo adicionamos o dados de telemetria ao tracer a partir do batch declarado acima: trace.get_tracer_provider().add_span_processor(span_processor) tracer = trace.get_tracer(__name__) with tracer.start_as_current_span("teste_com_span"): print("SRE and DevOps work together!!!")