From 778752e3a89807e2c5df7a1db0de9e0d3d60a995 Mon Sep 17 00:00:00 2001 From: Peter Dudfield <34686298+peterdudfield@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:27:55 +0000 Subject: [PATCH] log usage of package (#230) #minor * log usage of package * add "round_latitude_and_longitude" method * typo * text * PR comment --- README.md | 8 ++++ pyproject.toml | 1 + quartz_solar_forecast/forecast.py | 6 +++ quartz_solar_forecast/pydantic_models.py | 8 ++++ quartz_solar_forecast/utils/sentry_logging.py | 42 +++++++++++++++++++ 5 files changed, 65 insertions(+) create mode 100644 quartz_solar_forecast/utils/sentry_logging.py diff --git a/README.md b/README.md index 5de89ed..0df42ea 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,14 @@ conda install -c conda-forge pyresample This can solve the [bug: \_\_\_kmpc_for_static_fini](https://github.com/openclimatefix/Open-Source-Quartz-Solar-Forecast/issues/32). +### Logging + +The package logs when `run_forecast` is used. This is useful for OCF to determine how the package is being used +and how we can make improvements in the future. +Note that any latitudes and longitudes are rounded to 2 decimals places in order to anonymize the data. +If you would like to disable this logging, you can do so by setting the environment variable `QUARTZ_SOLAR_FORECAST_LOGGING` to `False`. + + ## Model Two models are currently available to make predictions. diff --git a/pyproject.toml b/pyproject.toml index c6a7a4f..54f10d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ dependencies = [ "uvicorn", "pydantic_settings", "httpx", + "sentry_sdk" ] [project.urls] diff --git a/quartz_solar_forecast/forecast.py b/quartz_solar_forecast/forecast.py index a75647b..ba5eab5 100644 --- a/quartz_solar_forecast/forecast.py +++ b/quartz_solar_forecast/forecast.py @@ -6,6 +6,7 @@ from quartz_solar_forecast.data import get_nwp, make_pv_data from quartz_solar_forecast.forecasts import forecast_v1_tilt_orientation, TryolabsSolarPowerPredictor from quartz_solar_forecast.pydantic_models import PVSite +from quartz_solar_forecast.utils.sentry_logging import write_sentry log = logging.getLogger(__name__) @@ -124,6 +125,11 @@ def run_forecast( :return: The PV forecast of the site for time (ts) for 48 hours """ + # log usage to sentry, if you dont want to log usage to sentry, you can + # 1. set environmental variable QUARTZ_SOLAR_FORECAST_LOGGING='false', or + # 2. comment out this line + write_sentry({"site": site.copy(), "model": model, "ts": ts, "nwp_source": nwp_source}) + if model == "gb": return predict_ocf(site, None, ts, nwp_source) diff --git a/quartz_solar_forecast/pydantic_models.py b/quartz_solar_forecast/pydantic_models.py index 7dd2b30..9dee52b 100644 --- a/quartz_solar_forecast/pydantic_models.py +++ b/quartz_solar_forecast/pydantic_models.py @@ -33,6 +33,14 @@ class PVSite(BaseModel): json_schema_extra=["enphase", "solis", "givenergy", "solarman", None], ) + def round_latitude_and_longitude(self): + """ Round the latitude and longitude to 2 decimal places + + This is to ensure that the location of the site is not stored exactly. + """ + self.latitude = round(self.latitude, 2) + self.longitude = round(self.longitude, 2) + def get_inverter(self): if self.inverter_type == 'enphase': return EnphaseInverter(EnphaseSettings()) diff --git a/quartz_solar_forecast/utils/sentry_logging.py b/quartz_solar_forecast/utils/sentry_logging.py new file mode 100644 index 0000000..c34bd26 --- /dev/null +++ b/quartz_solar_forecast/utils/sentry_logging.py @@ -0,0 +1,42 @@ +""" Log usage of this package to Sentry """ + +import sentry_sdk +from quartz_solar_forecast.pydantic_models import PVSite + +import os + +quartz_solar_forecast_logging = os.getenv("QUARTZ_SOLAR_FORECAST_LOGGING", "True").lower() != "false" + +SENTRY_DSN = 'https://b2b6f3c97299f81464bc16ad0d516d0b@o400768.ingest.us.sentry.io/4508439933157376' +sentry_sdk.init( + dsn=SENTRY_DSN, + ) + + +def write_sentry(params): + """ + Log usage of this package to Sentry + """ + + if not quartz_solar_forecast_logging: + return + + try: + for key, value in params.items(): + + # we want to make sure we don't store the exact location of the site + if isinstance(value, PVSite): + value.round_latitude_and_longitude() + + # set sentry tag + sentry_sdk.set_tag(key, value) + + message = "quartz_solar_forecast is being used" + + if os.getenv("PYTEST_CURRENT_TEST") is not None: + message += ": in CI tests" + + sentry_sdk.capture_message(message) + + except Exception as _: # noqa + pass