Skip to content

Add multiprocessing to the Quidel indicator #1881

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Aug 10, 2023

Conversation

rzats
Copy link
Contributor

@rzats rzats commented Aug 3, 2023

Description

Parallelizes the long-running generate_sensor_for_*_geo functions in the Quidel indicator - see #1547

In a local test run, this change made the total runtime for the pull step of this indicator 4.2x faster, and the runtime of the generate functions 6x faster:

Indicator runtime before the parallelization

Indicator runtime before the parallelization - note the generate_sensor_for_parent_geo call...

Indicator runtime after the parallelization

Indicator runtime after the parallelization - generate call replaced by multiprocessing functions.

Changelog

  • Adds multiprocessing to Quidel indicator.

@rzats rzats requested review from melange396 and dshemetov August 3, 2023 20:42
@dshemetov
Copy link
Contributor

dshemetov commented Aug 3, 2023

Taken at face value and assuming you're testing on an 8 core machine, these results look believable and promising. Also nice that the code change is pretty simple!

Some questions about the benchmarks:

  • what profiler are you using to run your tests / generate your plots?
  • what datasets are being used in the tests? are you just running locally for the most recent data? are there any file downloads involved in the tests? are you clearing downloaded data in between runs? any other places that caching could be creeping in?
  • how does this profiler interact with parallelization? do threads running the same function aggregate their times spent? there doesn't seem to be much overlap between the two timing plots after the run.py block (the visible functions in the parallelized plot are mostly pool.py and threading.py, which aren't very informative)
  • can we get a memory profile? mostly it would be nice to know how big the memory usage of the typical thread is, so we don't OOM on the server with too many threads

@rzats
Copy link
Contributor Author

rzats commented Aug 3, 2023

@dshemetov

what profiler are you using to run your tests

The built-in cProfile - from the quidel directory after running make install:

env/bin/python  -m cProfile -s cumulative -o cprofile.stats -m delphi_quidel_covidtest

/ generate your plots?

snakeviz - after the run above,

env/bin/python -m snakeviz cprofile.stats

what datasets are being used in the tests? are you just running locally for the most recent data?

I limit the pull start & end dates to 2023-07-01 and 2023-08-01 respectively, which is a volume of data comparable to the daily indicator run (on prod, the Quidel indicator doesn't seem to limit these dates in a similar way, but rather relies on its local state to determine which data to download & process).

are there any file downloads involved in the tests?

Yes, some files are downloaded from S3 by the indicator itself - on the screenshots above you can see these as the second most time-consuming function, pull_quidel_covidtest; In the first run it's the light purple column next to generate_sensors_for_parent_geo. Across all runs with the same date parameters these take ~16-19 seconds to complete.

are you clearing downloaded data in between runs? any other places that caching could be creeping in?

Yep, I clear all of the indicator's outputs between runs, and for the test in the PR body I actually ran the multiprocessing version before the single-threaded version just in case. In fact, if this is not done between runs, the indicator will not process any new data at all, taking <5 seconds to run.

how does this profiler interact with parallelization? do threads running the same function aggregate their times spent? there doesn't seem to be much overlap between the two timing plots after the run.py block (the visible functions in the parallelized plot are mostly pool.py and threading.py, which aren't very informative)

Unfortunately the multiprocessing functions obscure the Pandas timings in the profiler, but the indicator itself keeps track of the time spent on the run and this matches the profiler's overall timing. The single-threaded run's summary reads:

{"elapsed_time_in_seconds": 384.55, "csv_export_count": 2326, "max_lag_in_days": 27, "oldest_final_export_date": "2023-07-07", "event": "Completed indicator run", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-03T19:49:55.588555Z"}

And the multi-threaded run's:

{"elapsed_time_in_seconds": 90.18, "csv_export_count": 2326, "max_lag_in_days": 27, "oldest_final_export_date": "2023-07-07", "event": "Completed indicator run", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-03T19:41:30.743390Z"}

can we get a memory profile? mostly it would be nice to know how big the memory usage of the typical thread is, so we don't OOM on the server with too many threads

Memory profilers aren't super helpful here, since the idea behind multiprocessing is to bypass the global interpreter lock by spawning a few different Python processes. mprof displays this output for the single-threaded version:

Figure_1

And this for the multi-processing version:

Figure_2

However, this output refers to the base process only; the faster version spawns processes that do use more memory overall. Just manually checking the system's memory usage suggests these take ~180MB per process, for a total of ~2.2GB.

@dshemetov
Copy link
Contributor

Thanks for answering all these questions @rzats! 🚀

the indicator itself keeps track of the time spent on the run and this matches the profiler's overall timing

Good to have that confirmation from outside timing functions 👍.

Just manually checking the system's memory usage suggests these take ~180MB per process, for a total of ~2.2GB.

Good to know! In case the prod indicator server has more than 8 cores, we can get an estimate of the memory needed to support them👍

No further questions. As long as we make sure machine memory is enough for all the cores, I'm happy to approve.

Copy link
Contributor

@melange396 melange396 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice job! i think we can make it even better, though!

@melange396
Copy link
Contributor

good questions, @dshemetov !

  • how does this profiler interact with parallelization?

the profiler doesnt seem to capture anything from the worker processes. the call tree diagram would lose much of its semantic meaning if that were the case: the sum of timing from all the child processes would exceed the wall clock time of the root call.

Just manually checking the system's memory usage suggests these take ~180MB per process, for a total of ~2.2GB.

howd you reach that value? base plus workers gives me 400M + 8*180M ~= 1.84G... wheres that extra 20% come from?

also, @rzats: given the previous difficulty in locally replicating the runtime of the prod jobs, plus the fact that theres a difference in spawn/fork behaviors on macos/unix multiprocessing implementations, you should unlink the automatic close of #1547. we can close it manually after we see a run of this code on prod.

export_start_date, export_end_date, # export args
log_filename, log_exceptions): # logger args
"""Generate sensors, create export CSV then return stats."""
logger = get_structured_logger(__name__, log_filename, log_exceptions)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because trying to pass the existing logger breaks multiprocessing:

AttributeError: Can't pickle local object 'BoundLoggerLazyProxy.bind.<locals>.finalized_bind'"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

damn, i should have seen that coming... :(
this is worth a comment in the code, something like # `logger` cannot be passed to a child process

however! this current implementation with the newly constructed loggers is susceptible to concurrency issues, as they are all going to be trying to write to the same file from different processes without a mutex. to alleviate this, you should be able to pass along a multiprocessing.Lock() to use as a context manager around logging operations. that does add some more verbosity to your generate_and_...() calls, but it will work for now -- i have an idea for something that is cleaner and reusable for situations like this in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i just created #1885 which could greatly simplify the logging stuff, removing the need for the lock and re-creating loggers, as soon as thats available

@rzats
Copy link
Contributor Author

rzats commented Aug 4, 2023

@melange396 fixed, re-requesting review! Also, with these changes the runtime was reduced even further down to ~65 seconds for the test query:

Screenshot 2023-08-04 at 19 53 43

howd you reach that value? base plus workers gives me 400M + 8*180M ~= 1.84G... wheres that extra 20% come from?

That's based on me recording the machine's peak memory usage before and during the test run, but it could have spiked a bit more for some unrelated OS reasons :) adding up the Python processes' memory usage alone makes it around 1.95GB

@rzats rzats requested a review from melange396 August 4, 2023 16:56
@dshemetov
Copy link
Contributor

dshemetov commented Aug 4, 2023

Enhancement (non-blocking): just noticed that all the threads work on the same data = df.copy() object. If that object is not mutated (I didn't check, but I doubt it is), then we could save memory by sharing it with subprocesses. Examples here and here.

@@ -55,6 +57,45 @@ def get_smooth_info(sensors, _SMOOTHERS):
smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE)
return smoothers

def generate_and_export_for_nonparent_geo(geo_groups, res_key, smooth, device,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method and generate_and_export_for_parent_geo() are EXTREMELY similar but not exactly (more than just in the name of the generate_sensor...() methods they use) -- can you annotate those differences in the code? similarly for the blocks under for geo_res in NONPARENT_GEO_RESOLUTIONS: and for geo_res in PARENT_GEO_RESOLUTIONS:.

export_start_date, export_end_date, # export args
log_filename, log_exceptions): # logger args
"""Generate sensors, create export CSV then return stats."""
logger = get_structured_logger(__name__, log_filename, log_exceptions)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

damn, i should have seen that coming... :(
this is worth a comment in the code, something like # `logger` cannot be passed to a child process

however! this current implementation with the newly constructed loggers is susceptible to concurrency issues, as they are all going to be trying to write to the same file from different processes without a mutex. to alleviate this, you should be able to pass along a multiprocessing.Lock() to use as a context manager around logging operations. that does add some more verbosity to your generate_and_...() calls, but it will work for now -- i have an idea for something that is cleaner and reusable for situations like this in the future.

@rzats
Copy link
Contributor Author

rzats commented Aug 7, 2023

@dshemetov the df.copy() object is mutated in geo_map, so that approach wouldn't work - each thread will have to keep its own version of the dataframe anyhow.

@melange396 applied your suggested changes, re-requesting review!

@rzats rzats requested a review from melange396 August 7, 2023 11:25
@melange396
Copy link
Contributor

this is looking pretty good. do you have the logging output from a test run?

@rzats
Copy link
Contributor Author

rzats commented Aug 8, 2023

@melange396 yep, here's an example of a run from yesterday:

{"event": "Pulling data received on 2023-07-01", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:42.827475Z"}
{"event": "Pulling data received on 2023-07-02", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:43.458294Z"}
{"event": "Pulling data received on 2023-07-03", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:43.804043Z"}
{"event": "Pulling data received on 2023-07-04", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:43.994368Z"}
{"event": "Pulling data received on 2023-07-05", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:44.295859Z"}
{"event": "Pulling data received on 2023-07-06", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:44.515616Z"}
{"event": "Pulling data received on 2023-07-07", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:44.850550Z"}
{"event": "Pulling data received on 2023-07-08", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:45.185667Z"}
{"event": "Pulling data received on 2023-07-09", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:45.621716Z"}
{"event": "Pulling data received on 2023-07-10", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:45.837142Z"}
{"event": "Pulling data received on 2023-07-11", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:46.048356Z"}
{"event": "Pulling data received on 2023-07-12", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:46.359534Z"}
{"event": "Pulling data received on 2023-07-13", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:46.889285Z"}
{"event": "Pulling data received on 2023-07-14", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:47.342332Z"}
{"event": "Pulling data received on 2023-07-15", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:47.775991Z"}
{"event": "Pulling data received on 2023-07-16", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:48.203550Z"}
{"event": "Pulling data received on 2023-07-17", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:48.612773Z"}
{"event": "Pulling data received on 2023-07-18", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:48.986929Z"}
{"event": "Pulling data received on 2023-07-19", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:49.653551Z"}
{"event": "Pulling data received on 2023-07-20", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:50.082845Z"}
{"event": "Pulling data received on 2023-07-21", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:50.735017Z"}
{"event": "Pulling data received on 2023-07-22", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:51.413667Z"}
{"event": "Pulling data received on 2023-07-23", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:51.953774Z"}
{"event": "Pulling data received on 2023-07-24", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:52.260679Z"}
{"event": "Pulling data received on 2023-07-25", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:52.570493Z"}
{"event": "Pulling data received on 2023-07-26", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:53.095492Z"}
{"event": "Pulling data received on 2023-07-27", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:53.640999Z"}
{"event": "Pulling data received on 2023-07-28", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:54.290747Z"}
{"event": "Pulling data received on 2023-07-29", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:54.976291Z"}
{"event": "Pulling data received on 2023-07-30", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:55.510394Z"}
{"event": "Pulling data received on 2023-07-31", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:55.983057Z"}
{"event": "Pulling data received on 2023-08-01", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:56.393585Z"}
{"event": "Removing 0.10% of unusual data", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:57.138127Z"}
{"event": "Fixing 13.58% of outdated data", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:57.153420Z"}
{"n_cpu": 8, "event": "Parallelizing sensor generation", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:57.828593Z"}
{"event": "Top-level exception occurred", "logger": "delphi_quidel_covidtest.run", "level": "error", "timestamp": "2023-08-07T10:53:58.858037Z", "exception": "Traceback (most recent call last):\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/runpy.py\", line 194, in _run_module_as_main\n    return _run_code(code, main_globals, None,\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/cProfile.py\", line 206, in <module>\n    main()\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/cProfile.py\", line 195, in main\n    runctx(code, globs, None, options.outfile, options.sort)\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/cProfile.py\", line 19, in runctx\n    return _pyprofile._Utils(Profile).runctx(statement, globals, locals,\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/profile.py\", line 62, in runctx\n    prof.runctx(statement, globals, locals)\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/cProfile.py\", line 100, in runctx\n    exec(cmd, globals, locals)\n  File \"<string>\", line 1, in <module>\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/runpy.py\", line 210, in run_module\n    return _run_code(code, {}, init_globals, run_name, mod_spec)\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/Users/work/Documents/covidcast-indicators/quidel_covidtest/delphi_quidel_covidtest/__main__.py\", line 12, in <module>\n    run_module(read_params())  # pragma: no cover\n  File \"/Users/work/Documents/covidcast-indicators/quidel_covidtest/delphi_quidel_covidtest/run.py\", line 236, in run_module\n    pool_results = [proc.get() for proc in pool_results]\n  File \"/Users/work/Documents/covidcast-indicators/quidel_covidtest/delphi_quidel_covidtest/run.py\", line 236, in <listcomp>\n    pool_results = [proc.get() for proc in pool_results]\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/pool.py\", line 771, in get\n    raise self._value\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/pool.py\", line 537, in _handle_tasks\n    put(task)\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/connection.py\", line 206, in send\n    self._send_bytes(_ForkingPickler.dumps(obj))\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/reduction.py\", line 51, in dumps\n    cls(buf, protocol).dump(obj)\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/synchronize.py\", line 101, in __getstate__\n    context.assert_spawning(self)\n  File \"/usr/local/Cellar/[email protected]/3.8.16/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/context.py\", line 359, in assert_spawning\n    raise RuntimeError(\nRuntimeError: Lock objects should only be shared between processes through inheritance"}
{"elapsed_time_in_seconds": 20.15, "csv_export_count": 0, "max_lag_in_days": [], "oldest_final_export_date": [], "event": "Completed indicator run", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:53:58.859814Z"}
{"event": "Pulling data received on 2023-07-01", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:52.312688Z"}
{"event": "Pulling data received on 2023-07-02", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:53.473507Z"}
{"event": "Pulling data received on 2023-07-03", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:54.372587Z"}
{"event": "Pulling data received on 2023-07-04", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:54.899196Z"}
{"event": "Pulling data received on 2023-07-05", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:55.787222Z"}
{"event": "Pulling data received on 2023-07-06", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:56.526079Z"}
{"event": "Pulling data received on 2023-07-07", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:57.535874Z"}
{"event": "Pulling data received on 2023-07-08", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:58.347740Z"}
{"event": "Pulling data received on 2023-07-09", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:59.225317Z"}
{"event": "Pulling data received on 2023-07-10", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:59.659656Z"}
{"event": "Pulling data received on 2023-07-11", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:57:59.984110Z"}
{"event": "Pulling data received on 2023-07-12", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:00.413255Z"}
{"event": "Pulling data received on 2023-07-13", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:01.061468Z"}
{"event": "Pulling data received on 2023-07-14", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:01.841298Z"}
{"event": "Pulling data received on 2023-07-15", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:02.167104Z"}
{"event": "Pulling data received on 2023-07-16", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:02.506554Z"}
{"event": "Pulling data received on 2023-07-17", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:02.818434Z"}
{"event": "Pulling data received on 2023-07-18", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:03.015452Z"}
{"event": "Pulling data received on 2023-07-19", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:03.464696Z"}
{"event": "Pulling data received on 2023-07-20", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:03.856587Z"}
{"event": "Pulling data received on 2023-07-21", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:04.274279Z"}
{"event": "Pulling data received on 2023-07-22", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:04.566248Z"}
{"event": "Pulling data received on 2023-07-23", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:04.899979Z"}
{"event": "Pulling data received on 2023-07-24", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:05.136547Z"}
{"event": "Pulling data received on 2023-07-25", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:05.314716Z"}
{"event": "Pulling data received on 2023-07-26", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:05.623163Z"}
{"event": "Pulling data received on 2023-07-27", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:05.974620Z"}
{"event": "Pulling data received on 2023-07-28", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:07.193898Z"}
{"event": "Pulling data received on 2023-07-29", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:07.554874Z"}
{"event": "Pulling data received on 2023-07-30", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:07.895846Z"}
{"event": "Pulling data received on 2023-07-31", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:08.248214Z"}
{"event": "Pulling data received on 2023-08-01", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:08.429535Z"}
{"event": "Removing 0.10% of unusual data", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:08.844356Z"}
{"event": "Fixing 13.58% of outdated data", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:08.864784Z"}
{"n_cpu": 8, "event": "Parallelizing sensor generation", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:09.515128Z"}
{"geo_res": "hhs", "sensor": "covid_ag_smoothed_pct_positive_age_0_4", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.213193Z"}
{"geo_res": "hhs", "sensor": "covid_ag_raw_pct_positive", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.219493Z"}
{"geo_res": "hhs", "sensor": "covid_ag_smoothed_pct_positive_age_5_17", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.239224Z"}
{"geo_res": "hhs", "sensor": "covid_ag_smoothed_pct_positive", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.250163Z"}
{"geo_res": "hhs", "sensor": "covid_ag_smoothed_pct_positive_age_18_49", "pid": 74807, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.261765Z"}
{"geo_res": "hhs", "sensor": "covid_ag_raw_pct_positive_age_5_17", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.268340Z"}
{"geo_res": "hhs", "sensor": "covid_ag_raw_pct_positive_age_18_49", "pid": 74808, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.294084Z"}
{"geo_res": "hhs", "sensor": "covid_ag_raw_pct_positive_age_0_4", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.316349Z"}
{"geo_res": "hhs", "sensor": "covid_ag_smoothed_pct_positive_age_50_64", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.440185Z"}
{"geo_res": "hhs", "sensor": "covid_ag_raw_pct_positive_age_50_64", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.462929Z"}
{"geo_res": "hhs", "sensor": "covid_ag_smoothed_pct_positive_age_65plus", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.490799Z"}
{"geo_res": "hhs", "sensor": "covid_ag_raw_pct_positive_age_65plus", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.513332Z"}
{"geo_res": "hhs", "sensor": "covid_ag_smoothed_pct_positive_age_0_17", "pid": 74807, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.517779Z"}
{"geo_res": "hhs", "sensor": "covid_ag_raw_pct_positive_age_0_17", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.522906Z"}
{"geo_res": "nation", "sensor": "covid_ag_smoothed_pct_positive", "pid": 74808, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.527626Z"}
{"geo_res": "nation", "sensor": "covid_ag_raw_pct_positive", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.532728Z"}
{"geo_res": "nation", "sensor": "covid_ag_smoothed_pct_positive_age_0_4", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.597144Z"}
{"geo_res": "nation", "sensor": "covid_ag_raw_pct_positive_age_0_4", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.626521Z"}
{"geo_res": "nation", "sensor": "covid_ag_smoothed_pct_positive_age_5_17", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.630187Z"}
{"geo_res": "nation", "sensor": "covid_ag_raw_pct_positive_age_5_17", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.660786Z"}
{"geo_res": "nation", "sensor": "covid_ag_smoothed_pct_positive_age_18_49", "pid": 74808, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.684197Z"}
{"geo_res": "nation", "sensor": "covid_ag_raw_pct_positive_age_18_49", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.685945Z"}
{"geo_res": "nation", "sensor": "covid_ag_smoothed_pct_positive_age_50_64", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.689728Z"}
{"geo_res": "nation", "sensor": "covid_ag_raw_pct_positive_age_50_64", "pid": 74807, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.715229Z"}
{"geo_res": "nation", "sensor": "covid_ag_smoothed_pct_positive_age_65plus", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.740771Z"}
{"geo_res": "nation", "sensor": "covid_ag_raw_pct_positive_age_65plus", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.742979Z"}
{"geo_res": "nation", "sensor": "covid_ag_smoothed_pct_positive_age_0_17", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.775199Z"}
{"geo_res": "nation", "sensor": "covid_ag_raw_pct_positive_age_0_17", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.779646Z"}
{"geo_res": "state", "sensor": "covid_ag_smoothed_pct_positive", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.804622Z"}
{"geo_res": "state", "sensor": "covid_ag_raw_pct_positive", "pid": 74807, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.822429Z"}
{"geo_res": "state", "sensor": "covid_ag_smoothed_pct_positive_age_0_4", "pid": 74808, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.833514Z"}
{"geo_res": "state", "sensor": "covid_ag_raw_pct_positive_age_0_4", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.839909Z"}
{"geo_res": "state", "sensor": "covid_ag_smoothed_pct_positive_age_5_17", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.846941Z"}
{"geo_res": "state", "sensor": "covid_ag_raw_pct_positive_age_5_17", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.895267Z"}
{"geo_res": "state", "sensor": "covid_ag_smoothed_pct_positive_age_18_49", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.925930Z"}
{"geo_res": "state", "sensor": "covid_ag_raw_pct_positive_age_18_49", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:11.942574Z"}
{"geo_res": "state", "sensor": "covid_ag_smoothed_pct_positive_age_50_64", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.284856Z"}
{"geo_res": "state", "sensor": "covid_ag_raw_pct_positive_age_50_64", "pid": 74807, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.309192Z"}
{"geo_res": "state", "sensor": "covid_ag_smoothed_pct_positive_age_65plus", "pid": 74808, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.328305Z"}
{"geo_res": "state", "sensor": "covid_ag_raw_pct_positive_age_65plus", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.345184Z"}
{"geo_res": "state", "sensor": "covid_ag_smoothed_pct_positive_age_0_17", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.374258Z"}
{"geo_res": "state", "sensor": "covid_ag_raw_pct_positive_age_0_17", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.380012Z"}
{"geo_res": "county", "sensor": "covid_ag_smoothed_pct_positive", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.453695Z"}
{"geo_res": "county", "sensor": "covid_ag_raw_pct_positive", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.509941Z"}
{"geo_res": "county", "sensor": "covid_ag_smoothed_pct_positive_age_0_4", "pid": 74807, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.775496Z"}
{"geo_res": "county", "sensor": "covid_ag_raw_pct_positive_age_0_4", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.805894Z"}
{"geo_res": "county", "sensor": "covid_ag_smoothed_pct_positive_age_5_17", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.871446Z"}
{"geo_res": "county", "sensor": "covid_ag_raw_pct_positive_age_5_17", "pid": 74808, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.925023Z"}
{"geo_res": "county", "sensor": "covid_ag_smoothed_pct_positive_age_18_49", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:12.971046Z"}
{"geo_res": "county", "sensor": "covid_ag_raw_pct_positive_age_18_49", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:13.064351Z"}
{"geo_res": "county", "sensor": "covid_ag_smoothed_pct_positive_age_50_64", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:30.876878Z"}
{"geo_res": "county", "sensor": "covid_ag_raw_pct_positive_age_50_64", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:31.003353Z"}
{"geo_res": "county", "sensor": "covid_ag_smoothed_pct_positive_age_65plus", "pid": 74808, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:31.082963Z"}
{"geo_res": "county", "sensor": "covid_ag_raw_pct_positive_age_65plus", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:31.126836Z"}
{"geo_res": "county", "sensor": "covid_ag_smoothed_pct_positive_age_0_17", "pid": 74807, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:31.313289Z"}
{"geo_res": "county", "sensor": "covid_ag_raw_pct_positive_age_0_17", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:31.354416Z"}
{"geo_res": "msa", "sensor": "covid_ag_smoothed_pct_positive", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:31.504727Z"}
{"geo_res": "msa", "sensor": "covid_ag_raw_pct_positive", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:31.630469Z"}
{"geo_res": "msa", "sensor": "covid_ag_smoothed_pct_positive_age_0_4", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:33.856354Z"}
{"geo_res": "msa", "sensor": "covid_ag_raw_pct_positive_age_0_4", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:33.904516Z"}
{"geo_res": "msa", "sensor": "covid_ag_smoothed_pct_positive_age_5_17", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:36.319526Z"}
{"geo_res": "msa", "sensor": "covid_ag_raw_pct_positive_age_5_17", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:36.414513Z"}
{"geo_res": "msa", "sensor": "covid_ag_smoothed_pct_positive_age_18_49", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:39.024639Z"}
{"geo_res": "msa", "sensor": "covid_ag_raw_pct_positive_age_18_49", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:39.088276Z"}
{"geo_res": "msa", "sensor": "covid_ag_smoothed_pct_positive_age_50_64", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:41.509561Z"}
{"geo_res": "msa", "sensor": "covid_ag_raw_pct_positive_age_50_64", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:41.723891Z"}
{"geo_res": "msa", "sensor": "covid_ag_smoothed_pct_positive_age_65plus", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:44.238286Z"}
{"geo_res": "msa", "sensor": "covid_ag_raw_pct_positive_age_65plus", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:44.246919Z"}
{"geo_res": "msa", "sensor": "covid_ag_smoothed_pct_positive_age_0_17", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:46.767143Z"}
{"geo_res": "msa", "sensor": "covid_ag_raw_pct_positive_age_0_17", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:46.960971Z"}
{"geo_res": "hrr", "sensor": "covid_ag_smoothed_pct_positive", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:49.754510Z"}
{"geo_res": "hrr", "sensor": "covid_ag_raw_pct_positive", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:49.784640Z"}
{"geo_res": "hrr", "sensor": "covid_ag_smoothed_pct_positive_age_0_4", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:51.687238Z"}
{"geo_res": "hrr", "sensor": "covid_ag_raw_pct_positive_age_0_4", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:51.857179Z"}
{"geo_res": "hrr", "sensor": "covid_ag_smoothed_pct_positive_age_5_17", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:52.202751Z"}
{"geo_res": "hrr", "sensor": "covid_ag_raw_pct_positive_age_5_17", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:52.299241Z"}
{"geo_res": "hrr", "sensor": "covid_ag_smoothed_pct_positive_age_18_49", "pid": 74808, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:52.411741Z"}
{"geo_res": "hrr", "sensor": "covid_ag_raw_pct_positive_age_18_49", "pid": 74802, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:52.474514Z"}
{"geo_res": "hrr", "sensor": "covid_ag_smoothed_pct_positive_age_50_64", "pid": 74807, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:52.570963Z"}
{"geo_res": "hrr", "sensor": "covid_ag_raw_pct_positive_age_50_64", "pid": 74803, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:52.643006Z"}
{"geo_res": "hrr", "sensor": "covid_ag_smoothed_pct_positive_age_65plus", "pid": 74805, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:54.567451Z"}
{"geo_res": "hrr", "sensor": "covid_ag_raw_pct_positive_age_65plus", "pid": 74801, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:54.622496Z"}
{"geo_res": "hrr", "sensor": "covid_ag_smoothed_pct_positive_age_0_17", "pid": 74806, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:55.265228Z"}
{"geo_res": "hrr", "sensor": "covid_ag_raw_pct_positive_age_0_17", "pid": 74804, "event": "Generating signal and exporting to CSV", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:55.369460Z"}
{"elapsed_time_in_seconds": 71.2, "csv_export_count": 2326, "max_lag_in_days": 31, "oldest_final_export_date": "2023-07-07", "event": "Completed indicator run", "logger": "delphi_quidel_covidtest.run", "level": "info", "timestamp": "2023-08-07T10:58:57.873801Z"}

Previously the timestamps followed the behavior you mentioned (timing when the job was queued, not actually ran) but that changed when the logging was moved to the multiprocessing workers.

@melange396
Copy link
Contributor

that logging output looks like it had a previous run in it that must have been from before you were using a Manager-based Lock, eh?!

if we merge this now, will you promise to come back and update it when #1885 is also merged? 🙏

@rzats
Copy link
Contributor Author

rzats commented Aug 9, 2023

@melange396 Oh yeah, looks like that caught a bit of an older run as well :) the first run failed since Locks can't be passed as a parameter to multiprocessing methods, there are dirty solutions to this (global variables) or cleaner (getting the Lock from a Manager, like in this PR or #1885)

And sure, I can work on updating various loggers in the indicators when that PR is merged!

Copy link
Contributor

@melange396 melange396 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good stuff!

@melange396 melange396 merged commit aa0eb70 into main Aug 10, 2023
@melange396 melange396 deleted the rzatserkovnyi/performance-optimizations branch August 10, 2023 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants