def create_span(operation_name, app_info={}, span_tags=None): try: tracer = ThundraTracer().get_instance() execution_context = ExecutionContextManager.get() parent_transaction_id = execution_context.transaction_id if execution_context.transaction_id else None trace_id = execution_context.trace_id if execution_context.trace_id else utils.create_uuid4() transaction_id = parent_transaction_id or utils.create_uuid4() scope = tracer.start_active_span( span_id=utils.create_uuid4(), operation_name=operation_name, trace_id=trace_id, transaction_id=transaction_id, start_time=utils.current_milli_time(), execution_context = execution_context ) span = scope.span span.domain_name = app_info.get("applicationDomainName") span.class_name = app_info.get("applicationClassName") span.service_name = app_info.get("applicationName") if span_tags: for key in span_tags.keys(): span.set_tag(key, span_tags[key]) return scope except Exception as e: logger.error("Handler_utils create_span error: {}".format(e)) pass return None
def test_whitelist(): config = { 'block': True, "whitelist": [{ "className": "HTTP", "tags": { "http.host": ["www.google.com", "www.yahoo.com"], "operation.type": ["*"] } }, { "className": "AWS-DynamoDB", "tags": { "aws.dynamodb.table.name": ["Users"], "operation.type": ["List", "Read", "Write", "Tagging", "PermissionsManagement"] } }] } sasl = SecurityAwareSpanListener.from_config(config) error_thrown = None # Test whitelisted tracer = ThundraTracer.get_instance() span = tracer.create_span(operation_name='test') span.set_tag("http.host", "www.google.com") span.set_tag(constants.SpanTags['TOPOLOGY_VERTEX'], True) span.set_tag(constants.SpanTags['OPERATION_TYPE'], "GET") span.class_name = "HTTP" try: sasl.on_span_started(span) except Exception as e: error_thrown = e assert error_thrown == None assert span.get_tag(constants.SecurityTags["VIOLATED"]) == None assert span.get_tag(constants.SecurityTags["BLOCKED"]) == None # Test span out of whitelist tracer = ThundraTracer.get_instance() span = tracer.create_span(operation_name='test') span.set_tag("http.host", "www.test.com") span.set_tag(constants.SpanTags['TOPOLOGY_VERTEX'], True) span.set_tag(constants.SpanTags['OPERATION_TYPE'], "GET") span.class_name = "HTTP" try: sasl.on_span_started(span) except Exception as e: error_thrown = e assert str( error_thrown) == "Operation was blocked due to security configuration" assert span.get_tag(constants.SecurityTags["VIOLATED"]) == True assert span.get_tag(constants.SecurityTags["BLOCKED"]) == True
def test_postgre_integration_callproc(): connection = psycopg2.connect(user='******', host='localhost', password='******', dbname='db') try: cursor = connection.cursor() cursor.callproc('multiply', (3, 5)) except PostgreError: pass finally: tracer = ThundraTracer.get_instance() postgre_span = tracer.get_spans()[1] assert postgre_span.domain_name == constants.DomainNames['DB'] assert postgre_span.class_name == constants.ClassNames['POSTGRESQL'] assert postgre_span.operation_name == 'db' assert postgre_span.get_tag(constants.SpanTags['OPERATION_TYPE']) is '' assert postgre_span.get_tag(constants.SpanTags['DB_INSTANCE']) == 'db' assert postgre_span.get_tag( constants.SpanTags['DB_HOST']) == 'localhost' assert postgre_span.get_tag( constants.SpanTags['DB_STATEMENT']) == 'multiply' assert postgre_span.get_tag( constants.SpanTags['DB_STATEMENT_TYPE']) == 'MULTIPLY' tracer.clear() connection.close()
def test_trace_return_values(trace_return_val): tracer = ThundraTracer.get_instance() nodes = tracer.get_spans() count = 0 for key in nodes: if key.operation_name == 'func_return_val': count += 1 assert count == 0 traceable_trace_return_val, func_return_val = trace_return_val response = func_return_val() active_span = None nodes = tracer.get_spans() for key in nodes: if key.operation_name == 'func_return_val': count += 1 active_span = key args = active_span.get_tag('method.args') assert args is None return_value = active_span.get_tag('method.return_value') assert return_value['type'] == type(response).__name__ assert return_value['value'] == response error = active_span.get_tag('error') assert error is None assert count == 1 assert traceable_trace_return_val.trace_args is False assert traceable_trace_return_val.trace_return_value is True assert traceable_trace_return_val.trace_error is True
def test_athena_list_query_executions(mock_actual_call, mock_athena_list_query_executions_response): mock_actual_call.return_value = mock_athena_list_query_executions_response try: client = boto3.client('athena', region_name='us-west-2') client.list_query_executions( NextToken='string', MaxResults=123, WorkGroup='string' ) except Exception as e: print(e) finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.class_name == 'AWS-Athena' assert span.domain_name == 'DB' assert span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'LIST' assert span.get_tag(constants.AwsSDKTags['REQUEST_NAME']) == 'ListQueryExecutions' assert span.get_tag(constants.SpanTags['DB_INSTANCE']) is None assert span.get_tag(constants.AthenaTags['S3_OUTPUT_LOCATION']) is None assert span.get_tag(constants.AthenaTags['REQUEST_QUERY_EXECUTION_IDS']) is None assert span.get_tag(constants.AthenaTags['RESPONSE_QUERY_EXECUTION_IDS']) == [ '98765432-1111-1111-1111-12345678910'] assert span.get_tag(constants.AthenaTags['REQUEST_NAMED_QUERY_IDS']) is None assert span.get_tag(constants.AthenaTags['RESPONSE_NAMED_QUERY_IDS']) is None assert span.get_tag(constants.DBTags['DB_STATEMENT']) is None
def test_athena_statement_masked(): ConfigProvider.set(config_names.THUNDRA_TRACE_INTEGRATIONS_AWS_ATHENA_STATEMENT_MASK, 'true') database = "test" table = "persons" query = "SELECT * FROM %s.%s where age = 10;" % (database, table) s3_output = 's3://athena-test-bucket/results/' try: client = boto3.client('athena', region_name='us-west-2') client.start_query_execution( QueryString=query, QueryExecutionContext={ 'Database': database }, ResultConfiguration={ 'OutputLocation': s3_output, } ) except: pass finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.class_name == 'AWS-Athena' assert span.domain_name == 'DB' assert span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'WRITE' assert span.get_tag(constants.AwsSDKTags['REQUEST_NAME']) == 'StartQueryExecution' assert span.get_tag(constants.SpanTags['DB_INSTANCE']) == database assert span.get_tag(constants.AthenaTags['S3_OUTPUT_LOCATION']) == s3_output assert span.get_tag(constants.AthenaTags['REQUEST_QUERY_EXECUTION_IDS']) is None assert span.get_tag(constants.DBTags['DB_STATEMENT']) is None
def test_firehose(mock_actual_call, mock_firehose_response): mock_actual_call.return_value = mock_firehose_response region = 'us-west-2' timestamp = 1553695200 md5 = "098f6bcd4621d373cade4e832627b4f6" links = [ region + ":" + "test-stream" + ":" + str(timestamp) + ":" + md5, region + ":" + "test-stream" + ":" + str(timestamp + 1) + ":" + md5, region + ":" + "test-stream" + ":" + str(timestamp + 2) + ":" + md5 ] try: firehose = boto3.client('firehose', region_name=region) firehose.put_record( DeliveryStreamName='test-stream', Record={ 'Data': 'test' } ) except botocore_errors: pass finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.class_name == 'AWS-Firehose' assert span.domain_name == 'Stream' assert span.get_tag('operation.type') == 'WRITE' assert span.get_tag('aws.firehose.stream.name') == 'test-stream' assert span.get_tag('aws.request.name') == 'PutRecord' assert sorted(span.get_tag(constants.SpanTags['TRACE_LINKS'])) == sorted(links)
def test_lambda_payload_masked(mock_actual_call, mock_lambda_response, wrap_handler_with_thundra, mock_event, mock_context): mock_actual_call.return_value = mock_lambda_response ConfigProvider.set(config_names.THUNDRA_TRACE_INTEGRATIONS_AWS_LAMBDA_PAYLOAD_MASK, 'true') def handler(event, context): lambda_func = boto3.client('lambda', region_name='us-west-2') lambda_func.invoke( FunctionName='Test', InvocationType='RequestResponse', Payload=b"{\"name\": \"thundra\"}" ) with mock.patch('thundra.opentracing.recorder.ThundraRecorder.clear'): thundra, wrapped_handler = wrap_handler_with_thundra(handler) try: wrapped_handler(mock_event, mock_context) except: pass # Check span tags tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.class_name == 'AWS-Lambda' assert span.domain_name == 'API' assert span.get_tag('aws.lambda.name') == 'Test' assert span.get_tag('aws.lambda.qualifier') is None assert span.get_tag('aws.lambda.invocation.payload') is None assert span.get_tag('aws.request.name') == 'Invoke' assert span.get_tag('aws.lambda.invocation.type') == 'RequestResponse'
def test_refresh(): ConfigProvider.set( config_names.THUNDRA_TRACE_INTEGRATIONS_ELASTICSEARCH_PATH_DEPTH, '2') try: es = Elasticsearch([{'host': 'test', 'port': 3737}], max_retries=0) res = es.indices.refresh(index='test-index') print(res) except ElasticsearchException as e: pass finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.operation_name == '/test-index/_refresh' assert span.class_name == constants.ClassNames['ELASTICSEARCH'] assert span.domain_name == constants.DomainNames['DB'] assert span.get_tag( constants.ESTags['ES_HOSTS']) == ['http://test:3737'] assert span.get_tag( constants.ESTags['ES_URI']) == '/test-index/_refresh' assert span.get_tag(constants.ESTags['ES_BODY']) == {} assert span.get_tag(constants.DBTags['DB_TYPE']) == 'elasticsearch' assert span.get_tag(constants.SpanTags['TOPOLOGY_VERTEX'])
def test_get_doc(): ConfigProvider.set( config_names.THUNDRA_TRACE_INTEGRATIONS_ELASTICSEARCH_PATH_DEPTH, '3') try: es = Elasticsearch(['one_host', 'another_host'], max_retries=0) es.get(index='test-index', doc_type='tweet', id=1) except ElasticsearchException as e: pass finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] hosts = span.get_tag(constants.ESTags['ES_HOSTS']) assert span.operation_name == '/test-index/tweet/1' assert span.class_name == constants.ClassNames['ELASTICSEARCH'] assert span.domain_name == constants.DomainNames['DB'] assert len(hosts) == 2 assert 'http://one_host:9200' in hosts assert 'http://another_host:9200' in hosts assert span.get_tag(constants.ESTags['ES_METHOD']) == 'GET' assert span.get_tag( constants.ESTags['ES_URI']) == '/test-index/tweet/1' assert span.get_tag(constants.ESTags['ES_BODY']) == {} assert span.get_tag(constants.DBTags['DB_TYPE']) == 'elasticsearch' assert span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'GET' assert span.get_tag(constants.SpanTags['TOPOLOGY_VERTEX'])
def test_via_threadpool(): numbers = [1, 2, 3, 4, 5] squared_numbers = calculate_parallel(numbers, 4) expected_result = [1, 4, 9, 16, 25] assert squared_numbers == expected_result tracer = ThundraTracer.get_instance() nodes = tracer.get_spans() active_span = None for key in nodes: if key.operation_name == 'calculate_parallel': active_span = key args = active_span.get_tag('method.args') assert args[0]['name'] == 'arg-0' assert args[0]['value'] == numbers assert args[0]['type'] == 'list' assert args[1]['name'] == 'arg-1' assert args[1]['value'] == 4 assert args[1]['type'] == 'int' return_value = active_span.get_tag('method.return_value') assert return_value['value'] == squared_numbers assert return_value['type'] == 'list' error = active_span.get_tag('thrownError') assert error is None
def test_via_threading(): numbers = [1, 2, 3, 4, 5] expected_result = [1, 4, 9, 16, 25] wrapper = TraceAwareWrapper() thread = Thread(target=wrapper(calculate_in_parallel), args=(numbers, )) thread.start() thread.join() tracer = ThundraTracer.get_instance() nodes = tracer.get_spans() active_span = None for key in nodes: if key.operation_name == 'calculate_in_parallel': active_span = key assert active_span is not None args = active_span.get_tag('method.args') assert args[0]['name'] == 'arg-0' assert args[0]['value'] == numbers assert args[0]['type'] == 'list' return_value = active_span.get_tag('method.return_value') assert return_value['value'] == expected_result assert return_value['type'] == 'list' error = active_span.get_tag('error') assert error is None
def test_postgre_integration(): query = "select 1 + 1 AS solution" connection = psycopg2.connect(user='******', host='localhost', password='******', dbname='db') try: cursor = connection.cursor() cursor.execute(query) for table in cursor.fetchall(): print(table) finally: tracer = ThundraTracer.get_instance() postgre_span = tracer.get_spans()[1] assert postgre_span.domain_name == constants.DomainNames['DB'] assert postgre_span.class_name == constants.ClassNames['POSTGRESQL'] assert postgre_span.operation_name == 'db' assert postgre_span.get_tag( constants.SpanTags['OPERATION_TYPE']) == 'READ' assert postgre_span.get_tag(constants.SpanTags['DB_INSTANCE']) == 'db' assert postgre_span.get_tag( constants.SpanTags['DB_HOST']) == 'localhost' assert postgre_span.get_tag( constants.SpanTags['DB_STATEMENT']) == query assert postgre_span.get_tag( constants.SpanTags['DB_STATEMENT_TYPE']) == 'SELECT' connection.close()
def test_postgre_integration_with_empty_query(): connection = psycopg2.connect(user='******', host='localhost', password='******', dbname='db') try: cursor = connection.cursor() cursor.execute('') for table in cursor.fetchall(): print(table) except PostgreError: pass finally: tracer = ThundraTracer.get_instance() postgre_span = tracer.get_spans()[1] assert postgre_span.domain_name == constants.DomainNames['DB'] assert postgre_span.class_name == constants.ClassNames['POSTGRESQL'] assert postgre_span.operation_name == 'db' assert postgre_span.get_tag(constants.SpanTags['OPERATION_TYPE']) is '' assert postgre_span.get_tag(constants.SpanTags['DB_INSTANCE']) == 'db' assert postgre_span.get_tag( constants.SpanTags['DB_HOST']) == 'localhost' assert postgre_span.get_tag(constants.SpanTags['DB_STATEMENT']) == '' assert postgre_span.get_tag( constants.SpanTags['DB_STATEMENT_TYPE']) == '' connection.close()
def test_command_failed(): client = MongoClient('localhost', 27017) db = client.test try: for x in db.posts.find({}, {"field1": 1, "field2": 0}): print(x) except: pass tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.operation_name == 'test' assert span.class_name == constants.ClassNames['MONGODB'] assert span.domain_name == constants.DomainNames['DB'] assert span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'READ' assert span.get_tag(constants.DBTags['DB_HOST']) == 'localhost' assert span.get_tag(constants.DBTags['DB_PORT']) == 27017 assert span.get_tag(constants.DBTags['DB_INSTANCE']) == 'test' assert span.get_tag( constants.MongoDBTags['MONGODB_COMMAND_NAME']) == 'FIND' assert span.get_tag(constants.SpanTags['TOPOLOGY_VERTEX']) assert span.get_tag('error') is True tracer.clear()
def test_create_index(): ConfigProvider.set( config_names.THUNDRA_TRACE_INTEGRATIONS_ELASTICSEARCH_PATH_DEPTH, '3') author1 = {"name": "Sidney Sheldon", "novels_count": 18} try: es = Elasticsearch([{'host': 'test', 'port': 3737}], max_retries=0) es.index(index='authors', doc_type='authors', body=author1, id=1) except ElasticsearchException as e: pass finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.operation_name == '/authors/authors/1' assert span.class_name == constants.ClassNames['ELASTICSEARCH'] assert span.domain_name == constants.DomainNames['DB'] assert span.get_tag( constants.ESTags['ES_HOSTS']) == ['http://test:3737'] assert span.get_tag(constants.ESTags['ES_URI']) == '/authors/authors/1' assert span.get_tag(constants.ESTags['ES_BODY']) == author1 assert span.get_tag(constants.DBTags['DB_TYPE']) == 'elasticsearch' assert span.get_tag(constants.SpanTags['TOPOLOGY_VERTEX'])
def test_dynamodb_put_item_resource(): ConfigProvider.set(config_names.THUNDRA_TRACE_INTEGRATIONS_AWS_DYNAMODB_TRACEINJECTION_ENABLE, 'true') item = { 'id': '3', 'text': 'test' } try: dynamodb = boto3.resource('dynamodb', region_name='eu-west-2') table = dynamodb.Table('test-table') table.put_item( TableName="test-table", Item=item, ) except botocore_errors: pass finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.class_name == 'AWS-DynamoDB' assert span.domain_name == 'DB' assert span.operation_name == 'test-table' assert span.get_tag("operation.type") == 'WRITE' assert span.get_tag("db.instance") == 'dynamodb.eu-west-2.amazonaws.com' assert span.get_tag('db.statement') == item assert span.get_tag('db.statement.type') == 'WRITE' assert span.get_tag('db.type') == 'aws-dynamodb' assert span.get_tag('aws.dynamodb.table.name') == 'test-table' assert span.get_tag(constants.SpanTags['TRACE_LINKS']) == ["SAVE:" + span.span_id]
def __init__(self, trace_args=None, trace_return_value=None, trace_error=True, trace_line_by_line=False, trace_lines_with_source=None, trace_local_variables=None): self._trace_args = trace_args if trace_args is None: self._trace_args = False self._trace_return_value = trace_return_value if trace_return_value is None: self._trace_return_value = False self._trace_lines_with_source = trace_lines_with_source if trace_lines_with_source is None: self._trace_lines_with_source = False self._trace_local_variables = trace_local_variables if trace_local_variables is None: self._trace_local_variables = False self._trace_error = trace_error self._trace_line_by_line = trace_line_by_line if trace_line_by_line: if trace_lines_with_source is None: self._trace_lines_with_source = True if trace_return_value is None: self._trace_return_value = True if trace_local_variables is None: self._trace_local_variables = True if trace_args is None: self._trace_args = True self._tracing = False self._tracer = ThundraTracer.get_instance()
def test_kinesis(mock_actual_call, mock_kinesis_response): mock_actual_call.return_value = mock_kinesis_response region = 'us-west-2' shard_id = 'shardId--000000000000' sequence_number = '49568167373333333333333333333333333333333333333333333333' try: kinesis = boto3.client('kinesis', region_name=region) kinesis.put_record( Data='STRING_VALUE', PartitionKey='STRING_VALUE', StreamName='STRING_VALUE', ExplicitHashKey='STRING_VALUE', SequenceNumberForOrdering='STRING_VALUE' ) except botocore_errors: pass finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.class_name == 'AWS-Kinesis' assert span.domain_name == 'Stream' assert span.get_tag('operation.type') == 'WRITE' assert span.get_tag('aws.kinesis.stream.name') == 'STRING_VALUE' assert span.get_tag('aws.request.name') == 'PutRecord' assert span.get_tag(constants.SpanTags['TRACE_LINKS']) == [ region + ':' + 'STRING_VALUE:' + shard_id + ':' + sequence_number]
def test_sqlalchemy_session_pqsql(): engine = set_up_engine_and_table( 'postgresql://*****:*****@localhost:5432/db') # create a configured "Session" class Session = sessionmaker(bind=engine) # create a Session session = Session() # create Movies pulp_fiction = Movie("Pulp Fiction", date(1995, 4, 14)) session.add(pulp_fiction) session.commit() session.close() tracer = ThundraTracer.get_instance() span = tracer.get_spans()[0] statement = "INSERT INTO movies (title, release_date) VALUES (%(title)s, %(release_date)s) RETURNING movies.id" assert span.domain_name == constants.DomainNames['DB'] assert span.class_name == constants.ClassNames['POSTGRESQL'] assert span.operation_name == 'db' assert span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'WRITE' assert span.get_tag(constants.SpanTags['DB_INSTANCE']) == 'db' assert span.get_tag(constants.SpanTags['DB_TYPE']) == "postgresql" assert span.get_tag(constants.SpanTags['DB_HOST']) == 'localhost' assert span.get_tag(constants.SpanTags['DB_STATEMENT']) == statement assert span.get_tag(constants.SpanTags['DB_STATEMENT_TYPE']) == 'INSERT'
def test_athena_start_query_execution(mock_actual_call, mock_athena_start_query_exec_response): mock_actual_call.return_value = mock_athena_start_query_exec_response database = "test" table = "persons" query = "SELECT * FROM %s.%s where age = 10;" % (database, table) s3_output = 's3://athena-test-bucket/results/' try: client = boto3.client('athena', region_name='us-west-2') client.start_query_execution( QueryString=query, QueryExecutionContext={ 'Database': database }, ResultConfiguration={ 'OutputLocation': s3_output, } ) except: pass finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.class_name == 'AWS-Athena' assert span.domain_name == 'DB' assert span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'WRITE' assert span.get_tag(constants.AwsSDKTags['REQUEST_NAME']) == 'StartQueryExecution' assert span.get_tag(constants.SpanTags['DB_INSTANCE']) == database assert span.get_tag(constants.AthenaTags['S3_OUTPUT_LOCATION']) == s3_output assert span.get_tag(constants.AthenaTags['REQUEST_QUERY_EXECUTION_IDS']) is None assert span.get_tag(constants.AthenaTags['RESPONSE_QUERY_EXECUTION_IDS']) == [ "98765432-1111-1111-1111-12345678910"] assert span.get_tag(constants.DBTags['DB_STATEMENT']) == query
def _before_cursor_execute(self, conn, cursor, statement, parameters, context, executemany): if not context: return tracer = ThundraTracer.get_instance() if not tracer.get_active_span(): return scope = tracer.start_active_span( operation_name=self.get_operation_name(conn), finish_on_close=False) context.scope = scope # Inject before span tags try: self.before_call(scope, conn, statement) except Exception as instrumentation_exception: e = { 'type': str(type(instrumentation_exception)), 'message': str(instrumentation_exception), 'traceback': traceback.format_exc(), 'time': time.time() } scope.span.set_tag('instrumentation_error', e) try: # Inform span that initialization completed scope.span.on_started() except Exception as e: logger.error(e)
def test_athena_create_named_query(mock_actual_call, mock_athena_create_named_query_response): mock_actual_call.return_value = mock_athena_create_named_query_response query = "SELECT * FROM persons where age = 10;" try: client = boto3.client('athena', region_name='us-west-2') client.create_named_query( QueryString=query, Database="test", Name="test", ) except Exception as e: print(e) finally: tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.class_name == 'AWS-Athena' assert span.domain_name == 'DB' assert span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'WRITE' assert span.get_tag(constants.AwsSDKTags['REQUEST_NAME']) == 'CreateNamedQuery' assert span.get_tag(constants.SpanTags['DB_INSTANCE']) is None assert span.get_tag(constants.AthenaTags['S3_OUTPUT_LOCATION']) is None assert span.get_tag(constants.AthenaTags['REQUEST_QUERY_EXECUTION_IDS']) is None assert span.get_tag(constants.AthenaTags['RESPONSE_QUERY_EXECUTION_IDS']) is None assert span.get_tag(constants.AthenaTags['REQUEST_NAMED_QUERY_IDS']) is None assert span.get_tag(constants.AthenaTags['RESPONSE_NAMED_QUERY_IDS']) == ["98765432-1111-1111-1111-12345678910"] assert span.get_tag(constants.DBTags['DB_STATEMENT']) == query
def test_mysql_integration_callproc(): connection = mysql.connector.connect(user='******', host='localhost', password='******', database='db', auth_plugin='mysql_native_password') try: cursor = connection.cursor() cursor.callproc('multiply') except MySQLError: pass finally: tracer = ThundraTracer.get_instance() mysql_span = tracer.get_spans()[1] assert mysql_span.domain_name == constants.DomainNames['DB'] assert mysql_span.class_name == constants.ClassNames['MYSQL'] assert mysql_span.operation_name == 'db' assert mysql_span.get_tag(constants.SpanTags['OPERATION_TYPE']) == '' assert mysql_span.get_tag(constants.SpanTags['DB_INSTANCE']) == 'db' assert mysql_span.get_tag(constants.SpanTags['DB_HOST']) == 'localhost' assert mysql_span.get_tag( constants.SpanTags['DB_STATEMENT']) == 'multiply' assert mysql_span.get_tag( constants.SpanTags['DB_STATEMENT_TYPE']) == 'MULTIPLY' connection.close()
def test_trace_with_default_configs(trace): tracer = ThundraTracer.get_instance() nodes = tracer.get_spans() count = 0 for key in nodes: if key.operation_name == 'func': count += 1 assert count == 0 traceable, func = trace func(arg='test') active_span = None nodes = tracer.get_spans() for key in nodes: if key.operation_name == 'func': count += 1 active_span = key args = active_span.get_tag('method.args') assert args is None return_value = active_span.get_tag('method.return_value') assert return_value is None error = active_span.get_tag('error') assert error is None assert count == 1 assert traceable.trace_args is False assert traceable.trace_return_value is False assert traceable.trace_error is True
def test_mysql_integration(): query = "SELECT 1 + 1 AS solution" connection = mysql.connector.connect(user='******', host='localhost', password='******', database='db', auth_plugin='mysql_native_password') try: cursor = connection.cursor() cursor.execute(query) for table in cursor.fetchall(): print(table) finally: tracer = ThundraTracer.get_instance() mysql_span = tracer.get_spans()[1] assert mysql_span.domain_name == constants.DomainNames['DB'] assert mysql_span.class_name == constants.ClassNames['MYSQL'] assert mysql_span.operation_name == 'db' assert mysql_span.get_tag( constants.SpanTags['OPERATION_TYPE']) == 'READ' assert mysql_span.get_tag(constants.SpanTags['DB_INSTANCE']) == 'db' assert mysql_span.get_tag(constants.SpanTags['DB_HOST']) == 'localhost' assert mysql_span.get_tag(constants.SpanTags['DB_STATEMENT']) == query assert mysql_span.get_tag( constants.SpanTags['DB_STATEMENT_TYPE']) == 'SELECT' connection.close()
def test_trace_error(trace_error): tracer = ThundraTracer.get_instance() nodes = tracer.get_spans() count = 0 for key in nodes: if key.operation_name == 'func_with_error': count += 1 assert count == 0 traceable, func_with_error = trace_error try: func_with_error() except: active_span = None nodes = tracer.get_spans() for key in nodes: if key.operation_name == 'func_with_error': count += 1 active_span = key args = active_span.get_tag('method.args') assert args is None return_value = active_span.get_tag('method.return_value') assert return_value is None thrown_error = active_span.get_tag('error.kind') assert thrown_error == 'Exception' assert count == 1 assert traceable.trace_args is False assert traceable.trace_return_value is False assert traceable.trace_error is True
def test_command_insert(): client = MongoClient('localhost', 27017) db = client.test post = { "author": "Mike", "text": "My first blog post!", "tags": ["mongodb", "python", "pymongo"] } db.posts.insert_one(post) tracer = ThundraTracer.get_instance() span = tracer.get_spans()[1] assert span.operation_name == 'test' assert span.class_name == constants.ClassNames['MONGODB'] assert span.domain_name == constants.DomainNames['DB'] assert span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'WRITE' assert span.get_tag(constants.DBTags['DB_HOST']) == 'localhost' assert span.get_tag(constants.DBTags['DB_PORT']) == 27017 assert span.get_tag(constants.DBTags['DB_INSTANCE']) == 'test' assert span.get_tag( constants.MongoDBTags['MONGODB_COMMAND_NAME']) == 'INSERT' assert span.get_tag(constants.SpanTags['TOPOLOGY_VERTEX']) mongo_command = loads( span.get_tag(constants.MongoDBTags['MONGODB_COMMAND'])) assert mongo_command.get('documents')[0].get( 'text') == "My first blog post!"
def test_operation_name(): config = { 'block': False, "blacklist": [{ "className": "HTTP", "operationName": ["www.google.com/test"], "tags": { "http.host": ["www.google.com"], "operation.type": [ "GET", "POST", "PUT", ] } }] } sasl = SecurityAwareSpanListener.from_config(config) error_thrown = None tracer = ThundraTracer.get_instance() span = tracer.create_span(operation_name='www.google.com/test') span.set_tag("http.host", "www.google.com") span.set_tag(constants.SpanTags['TOPOLOGY_VERTEX'], True) span.set_tag(constants.SpanTags['OPERATION_TYPE'], "GET") span.class_name = "HTTP" try: sasl.on_span_started(span) except Exception as e: error_thrown = e assert error_thrown == None assert span.get_tag(constants.SecurityTags["VIOLATED"]) == True
def test_http_put_body_masked(): try: ConfigProvider.set( config_names.THUNDRA_TRACE_INTEGRATIONS_HTTP_BODY_MASK, 'true') url = 'https://jsonplaceholder.typicode.com/users/3' parsed_url = urlparse(url) path = parsed_url.path normalized_path = "/users" query = parsed_url.query host = parsed_url.netloc requests.put(url, data={"message": "test"}) tracer = ThundraTracer.get_instance() http_span = tracer.get_spans()[1] assert http_span.operation_name == host + normalized_path assert http_span.domain_name == constants.DomainNames['API'] assert http_span.class_name == constants.ClassNames['HTTP'] assert http_span.get_tag(constants.SpanTags['OPERATION_TYPE']) == 'PUT' assert http_span.get_tag(constants.HttpTags['HTTP_METHOD']) == 'PUT' assert http_span.get_tag(constants.HttpTags['HTTP_URL']) == host + path assert http_span.get_tag(constants.HttpTags['HTTP_HOST']) == host assert http_span.get_tag(constants.HttpTags['HTTP_PATH']) == path assert http_span.get_tag(constants.HttpTags['QUERY_PARAMS']) == query assert http_span.get_tag(constants.HttpTags['BODY']) is None except Exception: raise finally: tracer.clear()