Netflix / flamescope

FlameScope is a visualization tool for exploring different time ranges as Flame Graphs.
Apache License 2.0
3k stars 168 forks source link

UnicodeDecodeError exception is raised when an unreadable file is in profile dir #182

Open JulienP1 opened 6 months ago

JulienP1 commented 6 months ago

When an unreadble file is present in profile directory the the exception UnicodeDecodeError: 'utf-8' codec can't decode byte 0x98 in position 1040: invalid start byte is raised and the gui is blocked at the home page.

I proposed to modify the _is_perf_file method of fileutil.py file in order to manage this case.

def _is_perf_file(file_path):
    f = get_file(file_path)
    try:
        for line in f:
            if (line[0] == '#'):
                continue
            r = event_regexp.search(line)
            if r:
                f.close()
                return 'perf'
            f.close()
            return 'trace_event'
    except:
        return 'unreadable'

def get_file(file_path):
    # ensure the file is below PROFILE_DIR:
    if not abspath(file_path).startswith(abspath(config.PROFILE_DIR)):
        raise InvalidFileError("File %s is not in PROFILE_DIR" % file_path)
    if not _validpath(file_path):
        raise InvalidFileError("Invalid characters or file %s does not exist." % file_path)
    mime = _get_file_mime(file_path)
    if mime in ['application/x-gzip', 'application/gzip']:
        return gzip.open(file_path, 'rt')
    elif mime == 'text/plain':
        return open(file_path, 'r')
    elif mime == 'application/octet-stream':
        return open(file_path, 'rb')
    else:
        raise InvalidFileError('Unknown mime type.')

@cached(cache=LRUCache(maxsize=1024))
def get_profile_type(file_path):
    mime = _get_file_mime(file_path)
    if mime == 'application/octet-stream':
        return 'nflxprofile'
    elif mime in ['text/plain', 'application/x-gzip', 'application/gzip']:
        return _is_perf_file(file_path)
    else:
        return 'unknown'

and profile_list.py file:

def get_profile_list():
    all_files = []
    for root, dirs, files in walk(join(config.PROFILE_DIR)):
        start = root[len(config.PROFILE_DIR) + 1:]
        print("ERROR: %s" % files)
        for f in files:
            if not f.startswith('.'):
                filename = join(start, f)
                file_path = join(config.PROFILE_DIR, filename)
                file_type = get_profile_type(file_path)
                if(file_type != "unreadable"):
                    all_files.append({
                        'filename': filename,
                        'type': file_type
                    })

    return all_files

With these modifications, the behavior of the home page will be the same as for a file starting by a dot character