Our Slack alerts give real-time and accurate location events to our customers. These alerts include an image showing the location activity on a map to provide our customers the complete picture to act upon. Link previews are obtained by capturing a screenshot of our dashboard view for the live event. In this post we take a peek under the hood to see what powers these screenshots and how you can setup a service to do the same.
What you need
- Google Chrome: a web browser to load the page
- Selenium WebDriver: a tool to control the web browser programmatically
- ChromeDriver: a server that enables the WebDriver to work on Chrome
- Xvfb: X window server that can run on machines without display hardware
- WebGL: to render map tiles correctly
docker run -it -p 4444:4444 -v /dev/shm:/dev/shm --privileged arjun27/docker-selenium:latest
We can use the WebDriver Python APIs to get screenshots once the service is up and running. We get these screenshots as base64 encoded strings for our alerts. We upload them to AWS S3 and attach respective links to the Slack message body.
from selenium import webdriver WEBDRIVER_LOCATION = 'http://DOCKERHOST:4444/wd/hub' def get_options(): ''' Chrome options for WebGL ''' chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-web-security') chrome_options.add_argument('--use-gl') chrome_options.add_argument('--ignore-gpu-blacklist') return chrome_options.to_capabilities() def get_screenshot_as_base64(link_url, window_size): ''' Get screenshot as base64 from selenium cluster for given link and window size. ''' selenium_url = WEBDRIVER_LOCATION driver = webdriver.Remote(command_executor=selenium_url, desired_capabilities=get_options()) driver.set_window_size(*window_size) driver.get(link_url) base64_image = driver.get_screenshot_as_base64() driver.quit() return base64_image
Interact with the DOM
The WebDriver APIs are built to drive the web browser just as a user would be able to. This means you can interact with the DOM elements: click them fill in forms and also wait for them to load before you take a screenshot.
Our dashboard views load map tiles asynchronously. Therefore the driver needs to wait for map tiles to be loaded before taking a screenshot. We achieved this by adding an empty proxy DOM element that is hidden until the map tiles have loaded. The driver waits for the screenshot until it can click this proxy DOM element.
driver.get(link_url) driver.implicitly_wait(5) # max timeout in seconds driver.find_element_by_id('map-loader').click() base64_image = driver.get_screenshot_as_base64()
The Selenium WebDriver adds a superpower to our stack making it possible to share location visualizations along with Slack and other alerts. How are you going to use it?
Subscribe to HyperTrack Blog: Imagine. Build. Repeat.
Get the latest posts delivered right to your inbox