Exemplo n.º 1
0
    def process(self, stack, value):
        # We always start with native
        current_frame = nflxprofile_pb2.StackFrame()
        current_frame.function_name = "(native)"
        current_frame.libtype = ""
        processed_stack = []
        current_stack = []
        for frame in stack:
            package = self.get_package(frame)

            if package == current_frame.function_name or self.should_skip(
                    frame.function_name):
                current_stack.append(frame)
                continue

            processed_stack.append(current_frame)

            current_frame = nflxprofile_pb2.StackFrame()
            current_frame.function_name = package
            current_frame.libtype = ""
            current_stack = []

        processed_stack.append(current_frame)

        return super().process(processed_stack, value)
Exemplo n.º 2
0
def _get_stack(nflxprofile_nodes,
               node_id,
               has_node_stack=False,
               pid_comm=None,
               **args):
    """Get node stack using parent pointers or predefined stack."""
    inverted = args.get("inverted", False)
    package_name = args.get("package_name", False)

    stack = []

    # package name, only need first node
    if package_name:
        function_name = nflxprofile_nodes[node_id].function_name
        if has_node_stack:
            # uses node stack format, can't use node's function name
            node_stack = nflxprofile_nodes[node_id].stack
            function_name = node_stack[-1].function_name
        sanitized_function_name = function_name.split(';')[0]
        function_name_arr = sanitized_function_name.split('/')
        for name in function_name_arr:
            stack_frame = nflxprofile_pb2.StackFrame()
            stack_frame.function_name = name
            stack_frame.libtype = nflxprofile_nodes[node_id].libtype
            stack.append(stack_frame)
        if inverted:
            return reversed(stack)
        return stack

    # has node stack calculated, returning that
    if has_node_stack:
        function_name = nflxprofile_nodes[node_id].function_name
        pid = nflxprofile_nodes[node_id].pid
        if pid_comm and pid and pid in pid_comm:
            function_name = pid_comm[pid]
        stack_frame = nflxprofile_pb2.StackFrame()
        stack_frame.function_name = function_name
        stack_frame.libtype = nflxprofile_nodes[node_id].libtype
        stack = [stack_frame] + list(nflxprofile_nodes[node_id].stack)
        if inverted:
            return reversed(stack)
        return stack

    # need to use parent id
    nflxprofile_node_id = node_id
    while True:
        nflxprofile_node = nflxprofile_nodes[nflxprofile_node_id]
        stack_frame = nflxprofile_pb2.StackFrame()
        stack_frame.function_name = nflxprofile_node.function_name
        stack_frame.libtype = nflxprofile_node.libtype
        if inverted:
            stack.append(stack_frame)
        else:
            stack.insert(0, stack_frame)
        if not nflxprofile_nodes[nflxprofile_node_id].parent:
            break
        nflxprofile_node_id = nflxprofile_node.parent
    return stack
Exemplo n.º 3
0
    def process_frame(self, frame):
        """Process frame."""
        processed_frame = nflxprofile_pb2.StackFrame()
        processed_frame.CopyFrom(frame)
        name = frame.function_name
        name_parts = name.split('::')

        class_name = name_parts[0]
        class_name = class_name.split('$$')[0]

        if frame.libtype and frame.libtype in [
                'jit', 'inlined'
        ] and class_name.startswith("L"):
            class_name = class_name[1:]

        if class_name.endswith(';'):
            class_name = class_name[:-1]

        class_name = class_name.replace('/', '.')

        if len(name_parts) > 1:
            processed_frame.function_name = class_name + "::" + name_parts[1]
        else:
            processed_frame.function_name = class_name

        return processed_frame, FrameExtras()
Exemplo n.º 4
0
    def test_java_naming(self):
        tests = [
            {
                'input_name':
                'Ljava/util/concurrent/Executors$RunnableAdapter;::call',
                'libtype':
                'jit',
                'expected_name':
                'java.util.concurrent.Executors$RunnableAdapter::call',
            },
            {
                'input_name':
                'Ljava/util/concurrent/Executors$RunnableAdapter;::call',
                'libtype':
                'inlined',
                'expected_name':
                'java.util.concurrent.Executors$RunnableAdapter::call',
            },
            {
                'input_name': 'Ljava/util/concurrent/FutureTask;::run',
                'libtype': 'inlined',
                'expected_name': 'java.util.concurrent.FutureTask::run',
            },
            {
                'input_name':
                'Lcom/netflix/napa/SearchService$$EnhancerBySpringCGLIB$$65a2ea77;::searchNapa',
                'libtype': 'jit',
                'expected_name': 'com.netflix.napa.SearchService::searchNapa',
            },
            {
                'input_name':
                'Lio/grpc/stub/ServerCalls$UnaryServerCallHandler$UnaryServerCallListener;::onHalfClose',
                'libtype':
                'jit',
                'expected_name':
                'io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener::onHalfClose',
            },
            {
                'input_name':
                'Lcom/netflix/springboot/sso/grpcextensions/GrpcContextAspect$$Lambda$2611/1287052643;::call',  # noqa: E501
                'libtype':
                'inlined',
                'expected_name':
                'com.netflix.springboot.sso.grpcextensions.GrpcContextAspect::call',
            },
        ]

        jsp = flamegraph.JavaStackProcessor(None, None)

        for test in tests:
            stack_frame = nflxprofile_pb2.StackFrame()
            stack_frame.function_name = test['input_name']
            stack_frame.libtype = test['libtype']

            [processed, extras] = jsp.process_frame(stack_frame)
            self.assertEqual(processed.function_name, test['expected_name'])
Exemplo n.º 5
0
def _generate_regular_stacks(nflxprofile_nodes, root_node_id):
    stacks = {}
    queue = []
    queue.append((root_node_id, None))

    nodes = {}
    for node in nflxprofile_nodes:
        nodes[node['id']] = node

    while queue:
        (nflxprofile_node_id, parent_node_id) = queue.pop(0)
        node = nodes[nflxprofile_node_id]

        stack_frame = nflxprofile_pb2.StackFrame()

        call_frame = node.get('callFrame', node)
        filename = call_frame['url']
        line = call_frame['lineNumber']
        column = call_frame['columnNumber']
        function_name = call_frame['functionName'] or '(anonymous)'
        children = node.get('children', [])

        libtype = ''
        if function_name in ['(garbage collector)', '(root)'] or not filename.startswith('file://'):
            libtype = 'kernel'
        elif 'node_modules' in filename:
            libtype = 'user'
        else:
            libtype = 'jit'

        if filename:
            if  filename.startswith('file://'):
                filename = filename[7:]
            stack_frame.file.file_name = filename
            if line >= 0:
                stack_frame.file.line = line
            if column >= 0:
                stack_frame.file.column = column

        stack_frame.function_name = function_name
        stack_frame.libtype = libtype
        if not parent_node_id:
            stacks[nflxprofile_node_id] = [stack_frame]
        else:
            stacks[nflxprofile_node_id] = stacks[parent_node_id] + [stack_frame]
        for child_id in children:
            queue.append((child_id, nflxprofile_node_id))

    return stacks
Exemplo n.º 6
0
def _generate_package_name_stacks(nflxprofile_nodes):
    stacks = {}
    for key in nflxprofile_nodes:
        nflxprofile_node = nflxprofile_nodes[key]
        function_name = nflxprofile_node.function_name.split(';')[0]
        function_name_arr = function_name.split('/')
        stack_arr = []
        for package_name in function_name_arr:
            stack_frame = nflxprofile_pb2.StackFrame()
            stack_frame.function_name = package_name
            stack_frame.libtype = nflxprofile_node.libtype
            stack_arr.append(stack_frame)
        stacks[key] = stack_arr

    return stacks
Exemplo n.º 7
0
def _generate_regular_stacks(nflxprofile_nodes, root_node_id):
    stacks = {}
    queue = []
    queue.append((root_node_id, None))

    while queue:
        (nflxprofile_node_id, parent_node_id) = queue.pop(0)
        nflxprofile_node = nflxprofile_nodes[nflxprofile_node_id]
        stack_frame = nflxprofile_pb2.StackFrame()
        stack_frame.function_name = nflxprofile_node.function_name
        stack_frame.libtype = nflxprofile_node.libtype
        if not parent_node_id:
            stacks[nflxprofile_node_id] = [stack_frame]
        else:
            stacks[nflxprofile_node_id] = stacks[parent_node_id] + [stack_frame]
        for child_id in nflxprofile_node.children:
            queue.append((child_id, nflxprofile_node_id))

    return stacks
Exemplo n.º 8
0
    def process_frame(self, frame):
        """Process frame."""
        processed_frame = nflxprofile_pb2.StackFrame()
        processed_frame.CopyFrom(frame)
        name = frame.function_name

        name = name.split('::')[0]
        name = name.split('$$')[0]

        if frame.libtype and frame.libtype == 'jit' and name.startswith("L"):
            name = name[1:]

        if name.endswith(';'):
            name = name[:-1]

        name = name.replace('/', '.')

        processed_frame.function_name = name

        return processed_frame, FrameExtras()
Exemplo n.º 9
0
    def test_node_naming(self):
        tests = [
            {
                'input_name':
                'LazyCompile:processTicksAndRejections internal/process/task_queues.js:69',
                'libtype': 'jit',
                'expected_name': 'processTicksAndRejections',
                'extras': {
                    'javascript': True,
                    'optimized': True,
                    'real_name':
                    'LazyCompile:processTicksAndRejections internal/process/task_queues.js:69',
                    'v8_jit': True,
                },
            },
            {
                'input_name': 'Builtins_ArgumentsAdaptorTrampoline',
                'libtype': 'user',
                'expected_name': 'Builtins_ArgumentsAdaptorTrampoline',
                'extras': {
                    'javascript': False,
                    'optimized': None,
                    'real_name': 'Builtins_ArgumentsAdaptorTrampoline',
                    'v8_jit': False,
                },
            },
            {
                'input_name':
                'LazyCompile: /apps/nodequark/etc/routes/node_modules/@netflix-internal/naql-ipc/lib/ipc/AbstractClient.js:213',  # noqa: E501
                'libtype': 'jit',
                'expected_name': '(anonymous)',
                'extras': {
                    'javascript': True,
                    'optimized': True,
                    'real_name':
                    'LazyCompile: /apps/nodequark/etc/routes/node_modules/@netflix-internal/naql-ipc/lib/ipc/AbstractClient.js:213',  # noqa: E501
                    'v8_jit': True,
                },
            },
            {
                'input_name': 'v8::internal::LoadIC::Load',
                'libtype': 'user',
                'expected_name': 'v8::internal::LoadIC::Load',
                'extras': {
                    'javascript': False,
                    'optimized': None,
                    'real_name': 'v8::internal::LoadIC::Load',
                    'v8_jit': False,
                },
            },
            {
                'input_name':
                'Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit',
                'libtype': 'user',
                'expected_name':
                'Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit',
                'extras': {
                    'javascript': False,
                    'optimized': None,
                    'real_name':
                    'Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit',
                    'v8_jit': False,
                },
            },
            {
                'input_name':
                'InterpretedFunction:parseResponse /apps/nodequark/etc/routes/node_modules/restify-clients/lib/JsonClient.js:76',  # noqa: E501
                'libtype': 'jit',
                'expected_name': 'parseResponse',
                'extras': {
                    'javascript': True,
                    'optimized': False,
                    'real_name':
                    'InterpretedFunction:parseResponse /apps/nodequark/etc/routes/node_modules/restify-clients/lib/JsonClient.js:76',  # noqa: E501
                    'v8_jit': True,
                },
            },
            {
                'input_name':
                'node::LibuvStreamWrap::ReadStart()::{lambda(uv_stream_s*, long, uv_buf_t const*)#2}::_FUN',  # noqa: E501
                'libtype': 'user',
                'expected_name':
                'node::LibuvStreamWrap::ReadStart()::{lambda(uv_stream_s*, long, uv_buf_t const*)#2}::_FUN',  # noqa: E501
                'extras': {
                    'javascript': False,
                    'optimized': None,
                    'real_name':
                    'node::LibuvStreamWrap::ReadStart()::{lambda(uv_stream_s*, long, uv_buf_t const*)#2}::_FUN',  # noqa: E501
                    'v8_jit': False,
                },
            },
            {
                'input_name': 'smp_call_function_single',
                'libtype': 'kernel',
                'expected_name': 'smp_call_function_single',
                'extras': {
                    'javascript': False,
                    'optimized': None,
                    'real_name': 'smp_call_function_single',
                    'v8_jit': False,
                },
            },
            {
                'input_name': 'LazyCompile:*get bar /home/nfsuper/foo.js:1',
                'libtype': 'jit',
                'expected_name': 'get bar',
                'extras': {
                    'javascript': True,
                    'optimized': True,
                    'real_name': 'LazyCompile:*get bar /home/nfsuper/foo.js:1',
                    'v8_jit': True,
                },
            },
            {
                'input_name':
                'LazyCompile:get _hierarchy /apps/nodequark/etc/routes/node_modules/@netflix-internal/naql-core/lib/core/Query.js:65',  # noqa: E501
                'libtype': 'jit',
                'expected_name': 'get _hierarchy',
                'extras': {
                    'javascript': True,
                    'optimized': True,
                    'real_name':
                    'LazyCompile:get _hierarchy /apps/nodequark/etc/routes/node_modules/@netflix-internal/naql-core/lib/core/Query.js:65',  # noqa: E501
                    'v8_jit': True,
                },
            },
            {
                'input_name': 'LazyCompile:*a [eval]:1',
                'libtype': 'jit',
                'expected_name': 'a',
                'extras': {
                    'javascript': True,
                    'optimized': True,
                    'real_name': 'LazyCompile:*a [eval]:1',
                    'v8_jit': True,
                },
            },
        ]

        jsp = flamegraph.NodeJsStackProcessor(None, None)

        for test in tests:
            print(f"testing: {test['input_name']}")
            stack_frame = nflxprofile_pb2.StackFrame()
            stack_frame.function_name = test['input_name']
            stack_frame.libtype = test['libtype']

            [processed, extras] = jsp.process_frame(stack_frame)
            self.assertEqual(processed.function_name, test['expected_name'])
            self.assertEqual(dict_from_frame_extras(extras), test['extras'])