Skip to content

Commit

Permalink
add feature flag for retina screenshot support
Browse files Browse the repository at this point in the history
  • Loading branch information
eschutho committed Nov 13, 2021
1 parent aa8040e commit 80974e7
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 15 deletions.
32 changes: 24 additions & 8 deletions superset/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ def _try_json_readsha(filepath: str, length: int) -> Optional[str]:
# Use all X-Forwarded headers when ENABLE_PROXY_FIX is True.
# When proxying to a different port, set "x_port" to 0 to avoid downstream issues.
ENABLE_PROXY_FIX = False
PROXY_FIX_CONFIG = {"x_for": 1, "x_proto": 1, "x_host": 1, "x_port": 1, "x_prefix": 1}
PROXY_FIX_CONFIG = {"x_for": 1, "x_proto": 1,
"x_host": 1, "x_port": 1, "x_prefix": 1}

# ------------------------------
# GLOBALS FOR APP Builder
Expand Down Expand Up @@ -410,12 +411,13 @@ def _try_json_readsha(filepath: str, length: int) -> Optional[str]:
# This could cause the server to run out of memory or compute.
"ALLOW_FULL_CSV_EXPORT": False,
"UX_BETA": False,
"SCREENSHOTS_USE_RETINA_HIRES": False
}

# Feature flags may also be set via 'SUPERSET_FEATURE_' prefixed environment vars.
DEFAULT_FEATURE_FLAGS.update(
{
k[len("SUPERSET_FEATURE_") :]: parse_boolean_string(v)
k[len("SUPERSET_FEATURE_"):]: parse_boolean_string(v)
for k, v in os.environ.items()
if re.search(r"^SUPERSET_FEATURE_\w+", k)
}
Expand All @@ -438,7 +440,8 @@ def _try_json_readsha(filepath: str, length: int) -> Optional[str]:
# if hasattr(g, "user") and g.user.is_active:
# feature_flags_dict['some_feature'] = g.user and g.user.get_id() == 5
# return feature_flags_dict
GET_FEATURE_FLAGS_FUNC: Optional[Callable[[Dict[str, bool]], Dict[str, bool]]] = None
GET_FEATURE_FLAGS_FUNC: Optional[Callable[[
Dict[str, bool]], Dict[str, bool]]] = None
# A function that receives a feature flag name and an optional default value.
# Has a similar utility to GET_FEATURE_FLAGS_FUNC but it's useful to not force the
# evaluation of all feature flags when just evaluating a single one.
Expand Down Expand Up @@ -848,6 +851,8 @@ class CeleryConfig: # pylint: disable=too-few-public-methods
CSV_TO_HIVE_UPLOAD_DIRECTORY = "EXTERNAL_HIVE_TABLES/"
# Function that creates upload directory dynamically based on the
# database used, user and schema provided.


def CSV_TO_HIVE_UPLOAD_DIRECTORY_FUNC( # pylint: disable=invalid-name
database: "Database",
user: "models.User", # pylint: disable=unused-argument
Expand Down Expand Up @@ -951,7 +956,10 @@ def CSV_TO_HIVE_UPLOAD_DIRECTORY_FUNC( # pylint: disable=invalid-name
# Provide a callable that receives a tracking_url and returns another
# URL. This is used to translate internal Hadoop job tracker URL
# into a proxied one
TRACKING_URL_TRANSFORMER = lambda x: x


def TRACKING_URL_TRANSFORMER(x): return x


# Interval between consecutive polls when using Hive Engine
HIVE_POLL_INTERVAL = int(timedelta(seconds=5).total_seconds())
Expand Down Expand Up @@ -993,6 +1001,8 @@ def CSV_TO_HIVE_UPLOAD_DIRECTORY_FUNC( # pylint: disable=invalid-name
# def SQL_QUERY_MUTATOR(sql, user_name, security_manager, database):
# dttm = datetime.now().isoformat()
# return f"-- [SQL LAB] {username} {dttm}\n{sql}"


def SQL_QUERY_MUTATOR( # pylint: disable=invalid-name,unused-argument
sql: str,
user_name: Optional[str],
Expand Down Expand Up @@ -1026,7 +1036,8 @@ def SQL_QUERY_MUTATOR( # pylint: disable=invalid-name,unused-argument
ALERT_REPORTS_WORKING_TIME_OUT_LAG = int(timedelta(seconds=10).total_seconds())
# if ALERT_REPORTS_WORKING_TIME_OUT_KILL is True, set a celery hard timeout
# Equal to working timeout + ALERT_REPORTS_WORKING_SOFT_TIME_OUT_LAG
ALERT_REPORTS_WORKING_SOFT_TIME_OUT_LAG = int(timedelta(seconds=1).total_seconds())
ALERT_REPORTS_WORKING_SOFT_TIME_OUT_LAG = int(
timedelta(seconds=1).total_seconds())
# If set to true no notification is sent, the worker will just log a message.
# Useful for debugging
ALERT_REPORTS_NOTIFICATION_DRY_RUN = False
Expand Down Expand Up @@ -1215,7 +1226,10 @@ def SQL_QUERY_MUTATOR( # pylint: disable=invalid-name,unused-argument
# to allow mutating the object with this callback.
# This can be used to set any properties of the object based on naming
# conventions and such. You can find examples in the tests.
SQLA_TABLE_MUTATOR = lambda table: table


def SQLA_TABLE_MUTATOR(table): return table


# Global async query config options.
# Requires GLOBAL_ASYNC_QUERIES feature flag to be enabled.
Expand Down Expand Up @@ -1302,9 +1316,11 @@ def SQL_QUERY_MUTATOR( # pylint: disable=invalid-name,unused-argument
elif importlib.util.find_spec("superset_config") and not is_test():
try:
import superset_config # pylint: disable=import-error
from superset_config import * # type: ignore # pylint: disable=import-error,wildcard-import,unused-wildcard-import
# type: ignore # pylint: disable=import-error,wildcard-import,unused-wildcard-import
from superset_config import *

print(f"Loaded your LOCAL configuration at [{superset_config.__file__}]")
print(
f"Loaded your LOCAL configuration at [{superset_config.__file__}]")
except Exception:
logger.exception("Found but failed to import local superset_config")
raise
28 changes: 21 additions & 7 deletions superset/utils/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import logging
from enum import Enum
from superset.extensions import feature_flag_manager
from superset import config
from time import sleep
from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING

Expand All @@ -27,7 +29,7 @@
TimeoutException,
WebDriverException,
)
from selenium.webdriver import chrome, firefox
from selenium.webdriver import chrome, firefox, FirefoxProfile
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support import expected_conditions as EC
Expand Down Expand Up @@ -63,19 +65,28 @@ def create(self) -> WebDriver:
if self._driver_type == "firefox":
driver_class = firefox.webdriver.WebDriver
options = firefox.options.Options()
profile = FirefoxProfile()
if feature_flag_manager.is_feature_enabled("SCREENSHOTS_USE_RETINA_HIRES"):
profile.set_preference("layout.css.devPixelsPerPx", "2")
kwargs: Dict[Any, Any] = dict(
options=options, firefox_profile=profile)
elif self._driver_type == "chrome":
driver_class = chrome.webdriver.WebDriver
options = chrome.options.Options()
options.add_argument(f"--window-size={self._window[0]},{self._window[1]}")
if feature_flag_manager.is_feature_enabled("SCREENSHOTS_USE_RETINA_HIRES"):
options.add_argument("--force-device-scale-factor=2")
options.add_argument(
f"--window-size={self._window[0]},{self._window[1]}")
kwargs: Dict[Any, Any] = dict(options=options)
else:
raise Exception(f"Webdriver name ({self._driver_type}) not supported")
raise Exception(
f"Webdriver name ({self._driver_type}) not supported")
# Prepare args for the webdriver init

# Add additional configured options
for arg in current_app.config["WEBDRIVER_OPTION_ARGS"]:
options.add_argument(arg)

kwargs: Dict[Any, Any] = dict(options=options)
kwargs.update(current_app.config["WEBDRIVER_CONFIGURATION"])
logger.info("Init selenium driver")

Expand Down Expand Up @@ -135,12 +146,14 @@ def get_screenshot(
selenium_animation_wait = current_app.config[
"SCREENSHOT_SELENIUM_ANIMATION_WAIT"
]
logger.debug("Wait %i seconds for chart animation", selenium_animation_wait)
logger.debug("Wait %i seconds for chart animation",
selenium_animation_wait)
sleep(selenium_animation_wait)
logger.info("Taking a PNG screenshot of url %s", url)
img = element.screenshot_as_png
except TimeoutException:
logger.warning("Selenium timed out requesting url %s", url, exc_info=True)
logger.warning(
"Selenium timed out requesting url %s", url, exc_info=True)
img = element.screenshot_as_png
except StaleElementReferenceException:
logger.error(
Expand All @@ -151,5 +164,6 @@ def get_screenshot(
except WebDriverException as ex:
logger.error(ex, exc_info=True)
finally:
self.destroy(driver, current_app.config["SCREENSHOT_SELENIUM_RETRIES"])
self.destroy(
driver, current_app.config["SCREENSHOT_SELENIUM_RETRIES"])
return img

0 comments on commit 80974e7

Please sign in to comment.