bigsql / plprofiler

Other
79 stars 22 forks source link

AttributeError: 'NoneType' object has no attribute 'replace' - when generating plprofiler report #8

Closed markosutic closed 2 years ago

markosutic commented 2 years ago

Hello,

I am getting error AttributeError: 'NoneType' object has no attribute 'replace' when generating plprofiler report.

Environment: PostgreSQL 11.16 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit CentOS Linux release 7.9.2009 (Core)

To reproduce:

  1. Start monitor for global profiling (even tried to profile exact backend pid):

$ plprofiler monitor --interval=10 --duration=60 -d pgworkload

  1. Run sample queries/calls in separate session.

  2. Once data is captured run report.

$ plprofiler report --from-shared --title=TesProfileProc --output=TesProfileProc.html -d pgworkload

Traceback (most recent call last):
  File "/usr/local/bin/plprofiler", line 33, in <module>
    sys.exit(load_entry_point('plprofiler==4.1', 'console_scripts', 'plprofiler')())
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler_tool.py", line 66, in main
    return report_command(sys.argv[2:])
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler_tool.py", line 512, in report_command
    plp.report(report_data, output_fd)
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler.py", line 1012, in report
    report.generate(report_data, output_fd)
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler_report.py", line 49, in generate
    self.generate_function_output(config, func_def)
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler_report.py", line 87, in generate_function_output
    funcresult = func_def['funcresult'].replace(' ', '&nbsp;')))
AttributeError: 'NoneType' object has no attribute 'replace'
wieck commented 2 years ago

Did you add plprofiler to shared_preload_libraries and restart the postmaster?

markosutic commented 2 years ago

Yes, plprofiler was added to shared_preload_libraries with restart. I have also tested on Centos 8 and Postgres 14 but received same error. Export saved dataset into a JSON file is working.

wieck commented 2 years ago

Yes, plprofiler was added to shared_preload_libraries with restart. I have also tested on Centos 8 and Postgres 14 but received same error. Export saved dataset into a JSON file is working.

That is strange. I just tested on Rocky 8.5 with PG 14 and it went (mostly) fine. Something broke the flamegraph slightly. It no longer is interactive, but I have a hunch on that. In any case, I can't reproduce that failure here locally.

markosutic commented 2 years ago

If it helps I am sending example procedure. I can reproduce error even for session profiling. Please let me know if I can gather any diagnostic info to resolve this issue.

$ plprofiler run --command 'call test_proc()' -d pgworkload --output /tmp/test-prof1.html
call test_proc()
CALL (9.064 seconds)

Traceback (most recent call last):
  File "/usr/local/bin/plprofiler", line 11, in <module>
    load_entry_point('plprofiler==4.1', 'console_scripts', 'plprofiler')()
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler_tool.py", line 75, in main
    return run_command(sys.argv[2:])
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler_tool.py", line 846, in run_command
    plp.report(report_data, output_fd)
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler.py", line 1012, in report
    report.generate(report_data, output_fd)
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler_report.py", line 49, in generate
    self.generate_function_output(config, func_def)
  File "/usr/local/lib/python3.6/site-packages/plprofiler-4.1-py3.6.egg/plprofiler/plprofiler_report.py", line 87, in generate_function_output
    funcresult = func_def['funcresult'].replace(' ', '&nbsp;')))
AttributeError: 'NoneType' object has no attribute 'replace'
CREATE OR REPLACE PROCEDURE test_proc() LANGUAGE plpgsql SECURITY DEFINER
AS $$
declare
  history_rec record;
  cnt         integer;
begin

for history_rec in (select id, tid from pgbench_history where id between random()*(850000-1)+1 and random()*(850000-1)+1 limit 50)
  loop                
      update pgbench_history set mtime=clock_timestamp() where id between random()*(10000-1)+1 and random()*(10000-1)+1;

      select count(1) into cnt from pgbench_history where tid between random()*(1000-1)+1 and random()*(1000-1)+1;         
end loop;
END;
$$ ;

DB: PostgreSQL 14.3 OS: CentOS Linux release 8.5.2111

Thank you

wieck commented 2 years ago

With that I was able to reproduce the problem. It seems to be caused by test_proc being a procedure and not a function, but I am not entirely sure yet.

I'll keep digging.

wieck commented 2 years ago

@markosutic note that the default pgbench_history doesn't have an id column. I presume that is some sequence that you slapped on?

wieck commented 2 years ago

@markosutic fixed here: https://github.com/wieck/plprofiler/commit/8be48c7ec4acfbe4f37fd386a9fe4d17db8af99c

Note that the repositories have diverged. bigsql/plprofiler is stale and the new pgsql-io/plprofiler is messed up. Clone wieck/plprofiler until we sort this out.

markosutic commented 2 years ago

Yes. I have added id column for the test - sorry for not mentioning that. I have cloned "wieck/plprofiler" and run a test again. Now everything runs without an error.

Thank you!

wieck commented 2 years ago

Fixed in commit https://github.com/bigsql/plprofiler/commit/e9c08a0cb8b7f7bc0f7ff377ac7982bdbdc66c2c