<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Selenium – grid</title><link>https://trunk--polite-jelly-cc0866.netlify.app/tags/grid/</link><description>Recent content in grid on Selenium</description><generator>Hugo -- gohugo.io</generator><lastBuildDate>Fri, 19 Aug 2022 00:00:00 +0000</lastBuildDate><atom:link href="https://trunk--polite-jelly-cc0866.netlify.app/tags/grid/index.xml" rel="self" type="application/rss+xml"/><item><title>Blog: Scaling a Kubernetes Selenium Grid with KEDA</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/scaling-grid-with-keda/</link><pubDate>Fri, 19 Aug 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/scaling-grid-with-keda/</guid><description>
&lt;h2 id="the-issue">The Issue&lt;/h2>
&lt;p>If you have any experience with Selenium Grid and Kubernetes you will probably
run into an issue with scaling. Kubernetes (K8S) works wonders for scaling up and
down applications based on their CPU and Memory usage, but it is not so
straightforward when it comes down to applications like Selenium Grid.&lt;/p>
&lt;p>The issue is described quite well in &lt;a href="https://sahajamit.medium.com/spinning-up-your-own-auto-scalable-selenium-grid-in-kubernetes-part-2-15b11f228ed8">this blog post&lt;/a>.
But in short, the Horizontal Pod AutoScaler (HPA) that is built into
Kubernetes checks (by default) for resource consumption to determine
if a deployment needs to be scaled up or down. This becomes an issue
for Selenium Grid for a couple reasons:&lt;/p>
&lt;ol>
&lt;li>The browser pods use a variable amount of resources depending on
the demand of the current test. This means that all your browser pods
may be in use but there isn&amp;rsquo;t enough CPU usage for the HPA to decide
that a scale-up is needed, leaving tests waiting in the queue unnecessarily.&lt;/li>
&lt;li>When Kubernetes decides to scale down a deployment it does so
(for the most part) at random. You could have 10 tests running on
20 pods and need to scale down. More than likely at least one of
the pods asked to terminate will still have a test running, resulting
in connection failures.&lt;/li>
&lt;/ol>
&lt;h2 id="how-keda-helps">How KEDA Helps&lt;/h2>
&lt;p>&lt;a href="https://keda.sh/">KEDA&lt;/a> is a &lt;strong>free and open-source&lt;/strong> Kubernetes
event-driven autoscaling solution that extends the feature set of
K8S&amp;rsquo; HPA. This is done via plugins written by the community that
feed KEDA&amp;rsquo;s metrics server with the information it needs to scale
specific deployments up and down.&lt;/p>
&lt;p>Specifically for Selenium Grid, we have a &lt;a href="https://keda.sh/docs/latest/scalers/selenium-grid-scaler/">plugin&lt;/a>
that will tie into our grid to get the information it needs. Example of the used trigger:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">triggers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>- &lt;span style="color:#204a87;font-weight:bold">type&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-grid&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">url&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;http://selenium-grid-url-or-ip:4444/graphql&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">browserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;chrome&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>All of this gets saved as a Scaled-Object like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">apiVersion&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">keda.sh/v1alpha1&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">kind&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">ScaledObject&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">name&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-scaledobject&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">namespace&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">&amp;lt;namespace of your browser pods&amp;gt;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">labels&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">deploymentName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-node-deployment&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">minReplicaCount&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">maxReplicaCount&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">80&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">scaleTargetRef&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">name&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-node-deployment&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">triggers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>- &lt;span style="color:#204a87;font-weight:bold">type&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-grid&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">url&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;https://selenium-grid-url-or-ip:4444/graphql&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">browserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;chrome&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>As an added bonus KEDA allows us to scale our deployments down to
0 when there is no use, something the normal out-of-the-box HPA
does not allow.&lt;/p>
&lt;p>Check more details at &lt;a href="https://keda.sh/docs/latest/concepts/scaling-deployments/">the documentation for Scaled-Object in KEDA&lt;/a>.&lt;/p>
&lt;p>A full example of how to implement this is further down in the article
but KEDA solves one of our two issues. Now we can properly scale up and
down based on the actual load on the Selenium Grid. Unfortunately scaling
down still results in the likely possibility that a pod is still running
a test and is told to terminate before it can finish.&lt;/p>
&lt;h2 id="using-prestop-and-drain">Using PreStop and Drain&lt;/h2>
&lt;p>To combat this we are going to use a combination of K8s
&lt;a href="https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks">PreStop&lt;/a>
and Selenium Grid&amp;rsquo;s &lt;a href="https://www.selenium.dev/documentation/grid/advanced_features/endpoints/#drain-node">Drain&lt;/a>
functionality.&lt;/p>
&lt;ul>
&lt;li>&lt;code>PreStop&lt;/code> allows us to set a command or chain of commands that is run to completion before the container is told to stop.&lt;/li>
&lt;li>Drain tells the selenium browser pod to finish its current test and then shut down.&lt;/li>
&lt;/ul>
&lt;p>Together these look like so in our browser pod yaml:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">template&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">terminationGracePeriodSeconds&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">3600&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">...&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">...&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">containers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">lifecycle&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">preStop&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">exec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">command&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000;font-weight:bold">[&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;/bin/sh&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#34;-c&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#34;curl --request POST &amp;#39;localhost:5555/se/grid/node/drain&amp;#39; --header &amp;#39;X-REGISTRATION-SECRET;&amp;#39;; tail --pid=$(pgrep -f &amp;#39;[n]ode --bind-host false --config /opt/selenium/config.toml&amp;#39;) -f /dev/null; sleep 30s&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">]&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="breaking-this-down">Breaking this down&lt;/h4>
&lt;ul>
&lt;li>&lt;code>terminationGracePeriodSeconds&lt;/code> is set to however long you wish to give your
pods to gracefully terminate before being forced. In this case I give the pods
60 minutes to finish their test when asked to terminate. If you are also scaling
your cluster nodes as a part of this you may need to increase the termination
grace period for your cluster nodes as well.&lt;/li>
&lt;li>When the pod is told to stop, the &lt;code>PreStop&lt;/code> command is ran first.&lt;/li>
&lt;li>We curl the &lt;code>localhost&lt;/code> of our pod to tell it to drain. The pod will no
longer accept new session requests and will finish its current test. More
information on this &lt;a href="https://www.selenium.dev/documentation/grid/advanced_features/endpoints/#drain">can be found in the Selenium Grid documentation&lt;/a>.&lt;/li>
&lt;li>We then tail the internal node process that will continue to run until the node has been drained.&lt;/li>
&lt;li>After this we give the pod 30 seconds to finish anything else before giving the full termination command.&lt;/li>
&lt;/ul>
&lt;p>And with that our application can now safely scale down our selenium browser deployments!&lt;/p>
&lt;h2 id="from-start-to-finish">From Start to Finish&lt;/h2>
&lt;h3 id="install-keda">Install KEDA&lt;/h3>
&lt;ul>
&lt;li>You need to use version 2.8.0 or later, you can find the latest version number at the
&lt;a href="https://keda.sh/docs/latest/scalers/selenium-grid-scaler/">Selenium Grid Scaler docs&lt;/a>.&lt;/li>
&lt;li>&lt;code>kubectl apply -f https://github.com/kedacore/keda/releases/download/&amp;lt;Version_Number_Here&amp;gt;/keda-&amp;lt;Version_Number_Here&amp;gt;.yaml&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="create-and-apply-your-scaled-objects">Create and apply your scaled object(s)&lt;/h3>
&lt;p>As described earlier your &lt;a href="https://keda.sh/docs/latest/scalers/selenium-grid-scaler/">scaled object&lt;/a> will look like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">apiVersion&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">keda.sh/v1alpha1&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">kind&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">ScaledObject&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">name&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-scaledobject&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">namespace&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">&amp;lt;namespace of your browser pods&amp;gt;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">labels&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">deploymentName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-node-deployment&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">minReplicaCount&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">maxReplicaCount&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">80&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">scaleTargetRef&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">name&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-node-deployment&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">triggers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>- &lt;span style="color:#204a87;font-weight:bold">type&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-grid&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">url&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;https://selenium-grid-url-or-ip:4444/graphql&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">browserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;chrome&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You will need one of these for every browser you wish to scale.&lt;/p>
&lt;p>Things to edit:&lt;/p>
&lt;ol>
&lt;li>&lt;code>namespace&lt;/code> should be the namespace that your selenium browser pods exist in&lt;/li>
&lt;li>&lt;code>deploymentName&lt;/code> are the name of your browser deployment&lt;/li>
&lt;li>&lt;code>name&lt;/code> (within spec) is also the name of your browser deployment&lt;/li>
&lt;li>&lt;code>url&lt;/code> is the url of your selenium grid&lt;/li>
&lt;li>&lt;code>browserName&lt;/code> is the name of the browser you are using&lt;/li>
&lt;li>&lt;code>minReplicaCount&lt;/code> and &lt;code>maxReplicaCount&lt;/code> are the min and maximum pod count you want to have&lt;/li>
&lt;/ol>
&lt;p>If you plan to scale with Edge you will need at least version &lt;code>2.8.0&lt;/code> of KEDA and will
need to include &lt;code>sessionBrowserName&lt;/code> as well in the trigger metadata:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">triggers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>- &lt;span style="color:#204a87;font-weight:bold">type&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-grid&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">url&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;https://selenium-grid-url-or-ip:4444/graphql&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">browserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;MicrosoftEdge&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">sessionBrowserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;msedge&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is due to a name change between the Edge sessions in the queue and the active
sessions and is &lt;a href="https://github.com/kedacore/keda/pull/3062">addressed through this pull request&lt;/a>.&lt;/p>
&lt;p>Once you have that ready just save it as a yaml file and apply with:&lt;/p>
&lt;ul>
&lt;li>&lt;code>kubectl apply -f ./&amp;lt;scaled-object-file-name&amp;gt;.yaml --namespace=&amp;lt;browser_namespace&amp;gt;&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="add-prestop-commands-to-your-browser-pods">Add PreStop commands to your browser pods&lt;/h3>
&lt;ol>
&lt;li>Set your &lt;code>terminationGracePeriodSeconds&lt;/code> of your deployment to whatever the maximum
time you wish to give the pods in order to terminate gracefully. Again you may need to
also increase the grace period for your nodepool as well which will vary depending on
your K8s provider.&lt;/li>
&lt;li>Add the &lt;code>PreStop&lt;/code> command to the container lifecycle spec:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">template&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">terminationGracePeriodSeconds&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">3600&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">...&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">...&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">containers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">lifecycle&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">preStop&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">exec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">command&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000;font-weight:bold">[&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;/bin/sh&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#34;-c&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#34;curl --request POST &amp;#39;localhost:5555/se/grid/node/drain&amp;#39; --header &amp;#39;X-REGISTRATION-SECRET;&amp;#39;; tail --pid=$(pgrep -f &amp;#39;[n]ode --bind-host false --config /opt/selenium/config.toml&amp;#39;) -f /dev/null; sleep 30s&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">]&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That is it, your Selenium Grid pods should now scale up and down properly without any lost sessions!&lt;/p></description></item><item><title>Blog: Removing Legacy Protocol Support</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/legacy-protocol-support/</link><pubDate>Fri, 20 May 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/legacy-protocol-support/</guid><description>
&lt;p>The Selenium team prides itself on how seriously it takes backwards compatibility.
A lot of care has gone into the Java bindings, especially, to ensure very few breaking changes over the years.
There is Selenium code written 15 years ago that can still run with Selenium 4 libraries!
Providing this exceptional amount of support comes with a large maintenance burden, though,
and we need to be able to properly meet the needs of the vast majority of our userbase.&lt;/p>
&lt;p>TL/DR:&lt;/p>
&lt;ul>
&lt;li>Support for the legacy &lt;a href="https://www.selenium.dev/documentation/legacy/json_wire_protocol/">JSON Wire Protocol&lt;/a>
will be removed from Java Selenium 4.9 (other languages have already removed this support)&lt;/li>
&lt;li>Protocol conversions will stop in Selenium 4.9 Grid&lt;/li>
&lt;li>You can ensure your sessions are W3C compliant by using
&lt;a href="https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/#after">Browser Options classes&lt;/a>
instead of the deprecated Desired Capabilities classes (and avoid using &amp;ldquo;set capability&amp;rdquo; methods directly)&lt;/li>
&lt;li>If you rely on the current protocol conversion functionality, and it works for you,
you can continue to use it with Selenium Grid 4.8&lt;/li>
&lt;/ul>
&lt;p>By far the biggest challenge in the past seven years of Selenium development has been
transitioning the underlying implementation from the legacy &lt;a href="https://www.selenium.dev/documentation/legacy/json_wire_protocol/">JSON Wire Protocol&lt;/a>
to the new standardized &lt;a href="https://w3c.github.io/webdriver/">W3C WebDriver Protocol&lt;/a>.
Because the WebDriver specification was being actively developed at the time,
Selenium 3 supported both protocols simultaneously.
We implemented &amp;ldquo;handshake&amp;rdquo; code to determine which protocol to use.
When starting a session, Selenium would package the provided capabilities in both legacy and W3C formats,
send them to the driver/server, and use whichever protocol was returned.
This worked well for the most part. For many users, no changes were necessary to get
W3C compliant sessions from new browsers (Firefox 47+ and Chrome 75+).&lt;/p>
&lt;p>For the Java bindings, it was decided to take this approach one step further.
Instead of just sending along what was provided in both formats,
the code converted capabilities from the legacy protocol to the W3C protocol on behalf of the user.
The Selenium Grid makes use of this code, so, regardless of which client language sends legacy capabilities to it,
the Grid translates it to the W3C protocol for communication with the driver and then
re-translates the results back to the legacy protocol.
Because the code must make some assumptions and guesses for this to work, there are a lot of frustrating edge cases.&lt;/p>
&lt;p>For Selenium 4.0, the Ruby, JavaScript, and .NET bindings, each removed the handshake code,
so no legacy commands are used. Due to some issues that couldn&amp;rsquo;t be resolved before freezing the 3.x code,
Python is waiting until Selenium 4.9 to remove its handshake code.
The Selenium team intended to continue to support both protocols in the
Grid and Java bindings throughout the 4.x releases, but running test suites written for Selenium 2
on the Selenium 4 Grid resulted in a larger than expected number of failures.
Half a dozen bugs were discovered, some with a large effect.&lt;/p>
&lt;p>The code in question is sufficiently complex that fixing the bugs
without causing new problems would be a significant challenge.
As such, we’ve decided to start simplifying the code base again by explicitly
not supporting capabilities and commands from the legacy protocol in any of the Selenium codebase.
If you are using the latest version of Java Selenium, everything that will be removed
has already been marked deprecated, so double-check your usage to ensure there aren&amp;rsquo;t any surprises.&lt;/p>
&lt;p>If you’re interested in the nitty-gritty details of some of the issues we found
exploring this problem, you can look at the discussion in
&lt;a href="https://github.com/SeleniumHQ/selenium/issues/10374">Selenium Issue #10374&lt;/a>.&lt;/p>
&lt;p>For more information on ensuring compatibility with the Grid, please follow our
&lt;a href="https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/">Selenium 4 Upgrade Guide&lt;/a>&lt;/p></description></item><item><title>Blog: Observability in Selenium 4</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-4-observability/</link><pubDate>Mon, 26 Apr 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-4-observability/</guid><description>
&lt;p>Diagnosing problems when the Selenium server isn&amp;rsquo;t working has never been easy. With Selenium 4, we have integrated &lt;a href="https://opentelemetry.io/">OpenTelemetry&lt;/a> to help you troubleshoot issues, optimize performance, and provide visibility into the system. By making the Selenium server observable, we are putting more power into your hands.&lt;/p>
&lt;h3 id="need-for-observability">Need for Observability&lt;/h3>
&lt;p>Selenium server enables distributed testing. Instead of running the browsers for tests locally, the tests use a remote browser driver that points to a server. The server makes “&lt;strong>smart&lt;/strong>” decisions to run tests on different remote servers. Every such remote server is capable of hosting different types of browsers and browser versions.&lt;/p>
&lt;p>Selenium 3 uses Hub as the coordinator. It receives new session requests and directs them to the appropriate Node. The Node is the remote end where the browser itself runs.&lt;/p>
&lt;p>Selenium 4 extends this to provide users with a way to set up a full-blown distributed system. Essentially, &lt;a href="https://www.selenium.dev/documentation/en/grid/grid_4/components_of_a_grid/">Selenium 4&lt;/a> splits the Hub into different components with additional enhancements. However, the Node’s role remains the same. To ensure the backward compatibility and simplicity of setting up Grid, standalone and hub-node mode are also available in the new Selenium server.&lt;/p>
&lt;p>Now picture running a full-blown distributed Selenium Grid with hundreds of Nodes with different browsers and browser versions. Testing at scale in such an infrastructure will involve large volumes of requests. How can one keep track of these requests? Enter Selenium Observability!&lt;/p>
&lt;h3 id="how-does-selenium-provide-observability">How Does Selenium Provide Observability?&lt;/h3>
&lt;p>Selenium uses OpenTelemetry to instrument tracing and event logs. Tracing keeps track of a request’s lifecycle. As a request moves through the distributed system, the trace of the request will contain all the information of its crucial operations performed along the way. Such operations are known as spans. A span can record timed logs called events, which ideally encapsulate the current state of the system. These are event logs.&lt;/p>
&lt;p>By default, the Selenium server enables tracing. Selenium server can run in different modes:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.selenium.dev/documentation/en/grid/grid_4/setting_up_your_own_grid/#standalone-mode">Standalone&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.selenium.dev/documentation/en/grid/grid_4/setting_up_your_own_grid/#hub-and-node-mode">Hub and Node&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.selenium.dev/documentation/en/grid/grid_4/setting_up_your_own_grid/#distributed-mode">Fully Distributed&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/SeleniumHQ/docker-selenium#readme">Docker&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Tracing and event logs are available for all the modes. The simplest way to see traces is in the form of console logs. By default, the Selenium server prints logs at the INFO level and above. To pass a logging level of choice while running a Selenium Grid use the &lt;a href="https://www.selenium.dev/documentation/en/grid/grid_4/advanced_features/observability/#visualizing-traces">log-level&lt;/a> flag. Setting the log-level to FINE will display traces and event logs as console logs.&lt;/p>
&lt;p>For a large scale system, consuming traces as logs might not be efficient.
Visualizing and querying traces will quickly help troubleshoot a request failure easily. &lt;a href="https://www.jaegertracing.io/">Jaeger&lt;/a> seamlessly integrates with OpenTelemetry to provide a rich experience of querying, visualizing and collecting request traces.&lt;/p>
&lt;p>Run &lt;code> java -jar selenium-server-&amp;lt;selenium-version&amp;gt;.jar info tracing&lt;/code>.&lt;/p>
&lt;p>It provides detailed and updated instructions to set up Jaeger with the Selenium server.
Visualizing the traces makes it easy to interpret a trace and understand request flow. Now Grid users can effortlessly trace a request, drill down into an error or query them to observe what is happening.&lt;/p>
&lt;figure>
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/images/blog/2021/trace.png"
alt="Trace example"/>
&lt;/figure>
&lt;p>Refer to &lt;a href="https://www.selenium.dev/documentation/en/grid/grid_4/advanced_features/observability/">Selenium Observability&lt;/a> for details.&lt;/p>
&lt;h3 id="full-stack-tracing">Full-Stack Tracing&lt;/h3>
&lt;p>The Java client binding supports tracing. Full-stack tracing allows tracing a request from the client to the server and back. Though the client is a single component, the client trace will contain spans that help build the request. It is easier to locate a client-side problem and fix the test if needed.&lt;/p>
&lt;p>We already saw how the server supports tracing and how to leverage it. For the client-side, add the Opentelemetry dependency to your project setup and add the necessary system properties to export the traces to Jaeger. Refer to &lt;a href="https://www.selenium.dev/documentation/en/remote_webdriver/remote_webdriver_client/#tracing-client-requests">RemoteWebdriver client&lt;/a> for detailed instructions.&lt;/p>
&lt;h3 id="leveraging-traces-and-event-logs">Leveraging Traces and Event Logs&lt;/h3>
&lt;p>The key to fixing a problem lies in knowing the error. For a known error situation, the event logs have you covered. It provides detailed error information and stack traces. Query the collected traces for a time range by the error code to identify the frequency of the error. It will help determine if the error is transient or not and accordingly take action.&lt;/p>
&lt;figure>
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/images/blog/2021/error-event-log.png"
alt="Error event log example"/>
&lt;/figure>
&lt;p>Observe the request latency to identify potential bottlenecks. Each trace will also contain time taken by each span. The issue could be in the underlying infrastructure setup, the network latency, or the code itself. Irrespective of the cause, it is easier to identify the problem area.&lt;/p>
&lt;p>Observability is slowly becoming a must-have property of a system. Selenium is now observable! Go ahead try it out. Let us know if you find anything that requires improvement on our end.&lt;/p></description></item><item><title>Blog: Selenium Grid 1.0.8 Released</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/selenium-grid-1-0-8-released/</link><pubDate>Thu, 10 Jun 2010 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/selenium-grid-1-0-8-released/</guid><description>
&lt;p>We’re pleased to announce the release of Selenium Grid 1.0.8. This release fixes multithreaded issues with the Selenium Grid hub that appeared randomly under heavy load. If you’ve ever seen a log message about HttpClient being accessed by multiple threads, you definitely want to upgrade. Even if you haven’t, this release is highly recommended for all.&lt;/p>
&lt;p>You can &lt;a href="http://release.seleniumhq.org/selenium-grid/selenium-grid-1.0.8-bin.zip">download it now&lt;/a> or &lt;a href="http://github.com/nirvdrum/selenium-grid/blob/master/ChangeLog">view the changelog&lt;/a>. The list of changes is:&lt;/p>
&lt;ul>
&lt;li>Multi-threaded issue with access to HttpClient has been resolved, fixing random crashes on a heavily loaded grids&lt;/li>
&lt;/ul>
&lt;p>Many thanks go out to Chris Gulley for identifying and fixing the problem. As always, patches and bug reports are appreciated:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://github.com/nirvdrum/selenium-grid/">Code repository&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://code.google.com/p/selenium/issues/list">Issue tracker&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>I mentioned in the release notes for 1.0.7 that barring any major issues, 1.1 would be the next release. This fix was major enough to warrant an intermediate release. We are still planning to put out 1.1 as the next feature release.&lt;/p>
&lt;p>If you have any questions about Selenium Grid, please use either the user or the developer list, as is most appropriate for the nature of your question. Ongoing discussion about grid development should take place on the developer list.&lt;/p></description></item><item><title>Blog: Selenium Grid 1.0.7 Released</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/selenium-grid-1-0-7-released/</link><pubDate>Tue, 11 May 2010 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/selenium-grid-1-0-7-released/</guid><description>
&lt;p>Following up on the Selenium Grid 1.0.6 release, which was mostly a bug fix release, we’re pleased to announce the release of Selenium Grid 1.0.7. This is another bug fix release that focuses primarily on how Selenium Grid handles browser sessions.&lt;/p>
&lt;p>You can &lt;a href="http://release.seleniumhq.org/selenium-grid/selenium-grid-1.0.7-bin.zip">download it now&lt;/a> or &lt;a href="http://github.com/nirvdrum/selenium-grid/blob/master/ChangeLog">view the changelog&lt;/a>. The list of changes are:&lt;/p>
&lt;ul>
&lt;li>Hub now instructs remote controls to shutdown a session if the hub is going to remove it due to being idle for too long&lt;/li>
&lt;li>&lt;a href="http://selenium-grid.seleniumhq.org/configuring-and-tuning.html#changing_maximum_wait_time_for_new_session">Added ability to specify timeout period when waiting for remote controls to become available&lt;/a>. Now the client can timeout gracefully and decide what it would like to do next&lt;/li>
&lt;li>Handle common case of session ID not being found, either because it timed out or was already closed; rather than raising a NullPointerException we now raise a NoSuchSessionException&lt;/li>
&lt;li>Truncate long command response bodies to 128 characters&lt;/li>
&lt;li>Retry remote control checks up to three times before deciding that a remote control is unreliable or unresponsive. This prevents aggressive unregistration of hosts that are busy or suffer from network issues&lt;/li>
&lt;/ul>
&lt;p>As always, patches and bug reports are appreciated:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://github.com/nirvdrum/selenium-grid/">Code repository&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://code.google.com/p/selenium/issues/list">Issue tracker&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Barring any critical issues, the next release of Selenium Grid will be 1.1 and will feature an enhanced Web view as well as a status API. After that, we will be moving from GitHub to Google Code to live alongside the other Selenium projects.&lt;/p>
&lt;p>If you have any questions about Selenium Grid, please use either the user or the developer list, as is most appropriate for the nature of your question. Ongoing discussion about grid development should take place on the developer list.&lt;/p></description></item><item><title>Blog: The Future of Selenium Grid</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/the-future-of-selenium-grid/</link><pubDate>Tue, 27 Apr 2010 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/the-future-of-selenium-grid/</guid><description>
&lt;p>As you likely know by now, after years of stewardship Philippe has stepped down as maintainer of Selenium Grid and has named me the &lt;a href="http://ph7spot.com/blog/new-selenium-grid-maintainer">new maintainer.&lt;/a> In this post, I hope to address the most immediate questions about what this means for the future of Selenium Grid.&lt;/p>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>I realize many of you may not know who I am. I’ve been using Selenium in some capacity for close to five years now. I love working on open source software and do so primarily through my membership in the Apache Software Foundation and through &lt;a href="http://github.com/nirvdrum/">my GitHub account&lt;/a>. I hang out on the #selenium channel with the handle “nirvdrum” and have a &lt;a href="http://nirvdrum.com/">personal page&lt;/a> that includes some articles I’ve written and other things I’m involved with. Perhaps more importantly, I also rely on Selenium Grid for &lt;a href="http://mogotest.com/">my latest start-up&lt;/a> so I’m very keen on seeing the project mature and evolve.&lt;/p>
&lt;h2 id="project-resources">Project Resources&lt;/h2>
&lt;p>The new canonical project repository on GitHub is the &lt;a href="http://github.com/nirvdrum/selenium-grid/">nirvdrum fork&lt;/a>. However, within in the next month or so the project will be migrated from git and GitHub to subversion and the &lt;a href="http://code.google.com/p/selenium/">Selenium project on Google Code&lt;/a>. As much as I personally prefer GitHub to Google Code, it makes the most sense from a community perspective for all Selenium projects to be hosted in the same location. The move will be made after Selenium Grid stabilizes a bit more. The &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/selenium-grid-1-0-6-released/">1.0.6 release&lt;/a> was the first step in that process, but there may be one or two more minor patch releases. After the move, I’ll try to maintain a synchronized mirror of the code on GitHub so those that prefer to develop patches with git can continue to do so.&lt;/p>
&lt;p>The canonical issue tracker is the &lt;a href="http://code.google.com/p/selenium/issues/list">Selenium issue tracker&lt;/a> on Google Code. We will not be using either JIRA or GitHub Issues. I’ll try to migrate what I can over to the new tracker, but if I miss anything, please re-open the issue over there.&lt;/p>
&lt;h2 id="project-evolution">Project Evolution&lt;/h2>
&lt;p>Selenium Grid currently only works with Selenium 1.x, and consequently the 1.x compatibility interface in Selenium 2. There is currently no support for WebDriver. However, I fully intend to steer the product in that direction, while maintaining support for existing Selenium Grid installations (i.e., based on Selenium 1.x).&lt;/p>
&lt;p>Since the project is moving to Google Code, all of the existing Selenium committers will have the ability to commit to the codebase. This should make the project’s evolution a much more collaborative effort. I’ll kickstart the process and likely lead the development effort, but the role of maintainer will be diminished (in a positive way) by allowing the entire core team equal access to the project.&lt;/p>
&lt;p>Others are welcome to chime as well. Selenium Grid development discussion will be taking place on the Selenium developers list. Please continue to use the Selenium users list for usage and support inquiries.&lt;/p></description></item><item><title>Blog: Selenium Grid 1.0.6 Released</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/selenium-grid-1-0-6-released/</link><pubDate>Tue, 13 Apr 2010 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/selenium-grid-1-0-6-released/</guid><description>
&lt;p>Following up on the Selenium Grid 1.0.5 release, which added &lt;a href="http://selenium-grid.seleniumhq.org/self-healing.html">self-healing features&lt;/a> to ease grid management, we’re pleased to announce the release of Selenium Grid 1.0.6. This is a bug fix release for 1.0.5 with some minor new additions.&lt;/p>
&lt;p>You can &lt;a href="http://release.seleniumhq.org/selenium-grid/selenium-grid-1.0.6-bin.zip">download it now&lt;/a> or &lt;a href="http://github.com/nirvdrum/selenium-grid/blob/master/ChangeLog">view the changelog&lt;/a>. The summary of changes are:&lt;/p>
&lt;ul>
&lt;li>Fixed some concurrent modification issues that may have resulted in NullPointerExceptions&lt;/li>
&lt;li>Fixed issue with shutting down workers with Rakefile&lt;/li>
&lt;li>Added PID file support for hub and worker started via Rakefile, making it easier to use a process monitor such as monit&lt;/li>
&lt;/ul>
&lt;p>In case you missed the announcement, Philippe is &lt;a href="http://ph7spot.com/blog/selenium-grid-needs-a-new-maintainer">no longer maintaining&lt;/a> Selenium Grid. We thank him for his years of effort and helping the project get to where it is today. This is my first release as the &lt;a href="http://ph7spot.com/blog/new-selenium-grid-maintainer">new Selenium Grid maintainer&lt;/a>. I will be getting out a new post shortly that lays out the future for the project &lt;em>[UPDATE: The &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/the-future-of-selenium-grid/">promised post&lt;/a> is live]&lt;/em>. In the meanwhile, please note the new location of several key resources:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://github.com/nirvdrum/selenium-grid/">Code repository&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://code.google.com/p/selenium/issues/list">Issue tracker&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>If you have any questions about Selenium Grid, please use either the user or the developer list, as is most appropriate for the nature of your question. Ongoing discussion about grid development should take place on the developer list. We look forward to hearing what you think about how we can improve the project.&lt;/p></description></item></channel></rss>