Best Selenium code snippet using org.openqa.selenium.internal.Debug.getDebugLogLevel
Source:LocalDistributor.java
...18import static com.google.common.collect.ImmutableSet.toImmutableSet;19import static org.openqa.selenium.grid.data.Availability.DOWN;20import static org.openqa.selenium.grid.data.Availability.DRAINING;21import static org.openqa.selenium.grid.data.Availability.UP;22import static org.openqa.selenium.internal.Debug.getDebugLogLevel;23import static org.openqa.selenium.remote.RemoteTags.CAPABILITIES;24import static org.openqa.selenium.remote.RemoteTags.CAPABILITIES_EVENT;25import static org.openqa.selenium.remote.RemoteTags.SESSION_ID;26import static org.openqa.selenium.remote.RemoteTags.SESSION_ID_EVENT;27import static org.openqa.selenium.remote.tracing.AttributeKey.SESSION_URI;28import static org.openqa.selenium.remote.tracing.Tags.EXCEPTION;29import com.google.common.collect.ImmutableMap;30import com.google.common.collect.ImmutableSet;31import net.jodah.failsafe.Failsafe;32import net.jodah.failsafe.RetryPolicy;33import org.openqa.selenium.Beta;34import org.openqa.selenium.Capabilities;35import org.openqa.selenium.HealthCheckFailedException;36import org.openqa.selenium.ImmutableCapabilities;37import org.openqa.selenium.RetrySessionRequestException;38import org.openqa.selenium.SessionNotCreatedException;39import org.openqa.selenium.WebDriverException;40import org.openqa.selenium.concurrent.GuardedRunnable;41import org.openqa.selenium.events.EventBus;42import org.openqa.selenium.grid.config.Config;43import org.openqa.selenium.grid.data.Availability;44import org.openqa.selenium.grid.data.CreateSessionRequest;45import org.openqa.selenium.grid.data.CreateSessionResponse;46import org.openqa.selenium.grid.data.DistributorStatus;47import org.openqa.selenium.grid.data.NodeAddedEvent;48import org.openqa.selenium.grid.data.NodeDrainComplete;49import org.openqa.selenium.grid.data.NodeHeartBeatEvent;50import org.openqa.selenium.grid.data.NodeId;51import org.openqa.selenium.grid.data.NodeRemovedEvent;52import org.openqa.selenium.grid.data.NodeStatus;53import org.openqa.selenium.grid.data.NodeStatusEvent;54import org.openqa.selenium.grid.data.RequestId;55import org.openqa.selenium.grid.data.SessionRequest;56import org.openqa.selenium.grid.data.SessionRequestCapability;57import org.openqa.selenium.grid.data.Slot;58import org.openqa.selenium.grid.data.SlotId;59import org.openqa.selenium.grid.data.TraceSessionRequest;60import org.openqa.selenium.grid.distributor.Distributor;61import org.openqa.selenium.grid.distributor.GridModel;62import org.openqa.selenium.grid.distributor.config.DistributorOptions;63import org.openqa.selenium.grid.distributor.selector.SlotSelector;64import org.openqa.selenium.grid.log.LoggingOptions;65import org.openqa.selenium.grid.node.HealthCheck;66import org.openqa.selenium.grid.node.Node;67import org.openqa.selenium.grid.node.remote.RemoteNode;68import org.openqa.selenium.grid.security.Secret;69import org.openqa.selenium.grid.security.SecretOptions;70import org.openqa.selenium.grid.server.EventBusOptions;71import org.openqa.selenium.grid.server.NetworkOptions;72import org.openqa.selenium.grid.sessionmap.SessionMap;73import org.openqa.selenium.grid.sessionmap.config.SessionMapOptions;74import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;75import org.openqa.selenium.grid.sessionqueue.config.NewSessionQueueOptions;76import org.openqa.selenium.internal.Debug;77import org.openqa.selenium.internal.Either;78import org.openqa.selenium.internal.Require;79import org.openqa.selenium.remote.SessionId;80import org.openqa.selenium.remote.http.HttpClient;81import org.openqa.selenium.remote.tracing.AttributeKey;82import org.openqa.selenium.remote.tracing.EventAttribute;83import org.openqa.selenium.remote.tracing.EventAttributeValue;84import org.openqa.selenium.remote.tracing.Span;85import org.openqa.selenium.remote.tracing.Status;86import org.openqa.selenium.remote.tracing.Tracer;87import org.openqa.selenium.status.HasReadyState;88import java.io.Closeable;89import java.io.UncheckedIOException;90import java.net.URI;91import java.time.Duration;92import java.util.ArrayList;93import java.util.Collection;94import java.util.HashMap;95import java.util.List;96import java.util.Map;97import java.util.Optional;98import java.util.Set;99import java.util.concurrent.ConcurrentHashMap;100import java.util.concurrent.Executor;101import java.util.concurrent.Executors;102import java.util.concurrent.ScheduledExecutorService;103import java.util.concurrent.TimeUnit;104import java.util.concurrent.locks.Lock;105import java.util.concurrent.locks.ReadWriteLock;106import java.util.concurrent.locks.ReentrantReadWriteLock;107import java.util.logging.Level;108import java.util.logging.Logger;109import java.util.stream.Collectors;110public class LocalDistributor extends Distributor implements Closeable {111 private static final Logger LOG = Logger.getLogger(LocalDistributor.class.getName());112 private final Tracer tracer;113 private final EventBus bus;114 private final HttpClient.Factory clientFactory;115 private final SessionMap sessions;116 private final SlotSelector slotSelector;117 private final Secret registrationSecret;118 private final Map<NodeId, Runnable> allChecks = new HashMap<>();119 private final Duration healthcheckInterval;120 private final ReadWriteLock lock = new ReentrantReadWriteLock(/* fair */ true);121 private final GridModel model;122 private final Map<NodeId, Node> nodes;123 private final ScheduledExecutorService newSessionService =124 Executors.newSingleThreadScheduledExecutor(125 r -> {126 Thread thread = new Thread(r);127 thread.setDaemon(true);128 thread.setName("Local Distributor - New Session Queue");129 return thread;130 });131 private final ScheduledExecutorService purgeDeadNodesService =132 Executors.newSingleThreadScheduledExecutor(133 r -> {134 Thread thread = new Thread(r);135 thread.setDaemon(true);136 thread.setName("Local Distributor - Purge Dead Nodes");137 return thread;138 });139 private final ScheduledExecutorService nodeHealthCheckService =140 Executors.newSingleThreadScheduledExecutor(141 r -> {142 Thread thread = new Thread(r);143 thread.setDaemon(true);144 thread.setName("Local Distributor - Node Health Check");145 return thread;146 });147 private final Executor sessionCreatorExecutor = Executors.newFixedThreadPool(148 Runtime.getRuntime().availableProcessors(),149 r -> {150 Thread thread = new Thread(r);151 thread.setName("Local Distributor - Session Creation");152 thread.setDaemon(true);153 return thread;154 }155 );156 private final NewSessionQueue sessionQueue;157 private final boolean rejectUnsupportedCaps;158 public LocalDistributor(159 Tracer tracer,160 EventBus bus,161 HttpClient.Factory clientFactory,162 SessionMap sessions,163 NewSessionQueue sessionQueue,164 SlotSelector slotSelector,165 Secret registrationSecret,166 Duration healthcheckInterval,167 boolean rejectUnsupportedCaps,168 Duration sessionRequestRetryInterval) {169 super(tracer, clientFactory, registrationSecret);170 this.tracer = Require.nonNull("Tracer", tracer);171 this.bus = Require.nonNull("Event bus", bus);172 this.clientFactory = Require.nonNull("HTTP client factory", clientFactory);173 this.sessions = Require.nonNull("Session map", sessions);174 this.sessionQueue = Require.nonNull("New Session Request Queue", sessionQueue);175 this.slotSelector = Require.nonNull("Slot selector", slotSelector);176 this.registrationSecret = Require.nonNull("Registration secret", registrationSecret);177 this.healthcheckInterval = Require.nonNull("Health check interval", healthcheckInterval);178 this.model = new GridModel(bus);179 this.nodes = new ConcurrentHashMap<>();180 this.rejectUnsupportedCaps = rejectUnsupportedCaps;181 Require.nonNull("Session request interval", sessionRequestRetryInterval);182 bus.addListener(NodeStatusEvent.listener(this::register));183 bus.addListener(NodeStatusEvent.listener(model::refresh));184 bus.addListener(NodeRemovedEvent.listener(nodeStatus -> remove(nodeStatus.getNodeId())));185 bus.addListener(NodeHeartBeatEvent.listener(nodeStatus -> {186 if (nodes.containsKey(nodeStatus.getNodeId())) {187 model.touch(nodeStatus.getNodeId());188 } else {189 register(nodeStatus);190 }191 }));192 NewSessionRunnable newSessionRunnable = new NewSessionRunnable();193 bus.addListener(NodeDrainComplete.listener(this::remove));194 purgeDeadNodesService.scheduleAtFixedRate(195 GuardedRunnable.guard(model::purgeDeadNodes), 30, 30, TimeUnit.SECONDS);196 nodeHealthCheckService.scheduleAtFixedRate(197 runNodeHealthChecks(),198 this.healthcheckInterval.toMillis(),199 this.healthcheckInterval.toMillis(),200 TimeUnit.MILLISECONDS);201 // if sessionRequestRetryInterval is 0, we will schedule session creation every 10 millis202 long period = sessionRequestRetryInterval.isZero() ?203 10 : sessionRequestRetryInterval.toMillis();204 newSessionService.scheduleAtFixedRate(205 GuardedRunnable.guard(newSessionRunnable),206 sessionRequestRetryInterval.toMillis(),207 period,208 TimeUnit.MILLISECONDS209 );210 }211 public static Distributor create(Config config) {212 Tracer tracer = new LoggingOptions(config).getTracer();213 EventBus bus = new EventBusOptions(config).getEventBus();214 DistributorOptions distributorOptions = new DistributorOptions(config);215 HttpClient.Factory clientFactory = new NetworkOptions(config).getHttpClientFactory(tracer);216 SessionMap sessions = new SessionMapOptions(config).getSessionMap();217 SecretOptions secretOptions = new SecretOptions(config);218 NewSessionQueueOptions newSessionQueueOptions = new NewSessionQueueOptions(config);219 NewSessionQueue sessionQueue = newSessionQueueOptions.getSessionQueue(220 "org.openqa.selenium.grid.sessionqueue.remote.RemoteNewSessionQueue");221 return new LocalDistributor(222 tracer,223 bus,224 clientFactory,225 sessions,226 sessionQueue,227 distributorOptions.getSlotSelector(),228 secretOptions.getRegistrationSecret(),229 distributorOptions.getHealthCheckInterval(),230 distributorOptions.shouldRejectUnsupportedCaps(),231 newSessionQueueOptions.getSessionRequestRetryInterval());232 }233 @Override234 public boolean isReady() {235 try {236 return ImmutableSet.of(bus, sessions).parallelStream()237 .map(HasReadyState::isReady)238 .reduce(true, Boolean::logicalAnd);239 } catch (RuntimeException e) {240 return false;241 }242 }243 private void register(NodeStatus status) {244 Require.nonNull("Node", status);245 Lock writeLock = lock.writeLock();246 writeLock.lock();247 try {248 if (nodes.containsKey(status.getNodeId())) {249 return;250 }251 Set<Capabilities> capabilities = status.getSlots().stream()252 .map(Slot::getStereotype)253 .map(ImmutableCapabilities::copyOf)254 .collect(toImmutableSet());255 // A new node! Add this as a remote node, since we've not called add256 RemoteNode remoteNode = new RemoteNode(257 tracer,258 clientFactory,259 status.getNodeId(),260 status.getExternalUri(),261 registrationSecret,262 capabilities);263 add(remoteNode);264 } finally {265 writeLock.unlock();266 }267 }268 @Override269 public LocalDistributor add(Node node) {270 Require.nonNull("Node", node);271 // An exception occurs if Node heartbeat has started but the server is not ready.272 // Unhandled exception blocks the event-bus thread from processing any event henceforth.273 NodeStatus initialNodeStatus;274 try {275 initialNodeStatus = node.getStatus();276 model.add(initialNodeStatus);277 nodes.put(node.getId(), node);278 } catch (Exception e) {279 LOG.log(280 Debug.getDebugLogLevel(),281 String.format("Exception while adding Node %s", node.getUri()),282 e);283 return this;284 }285 // Extract the health check286 Runnable healthCheck = asRunnableHealthCheck(node);287 allChecks.put(node.getId(), healthCheck);288 updateNodeStatus(initialNodeStatus, healthCheck);289 LOG.info(String.format(290 "Added node %s at %s. Health check every %ss",291 node.getId(),292 node.getUri(),293 healthcheckInterval.toMillis() / 1000));294 bus.fire(new NodeAddedEvent(node.getId()));295 return this;296 }297 private void updateNodeStatus(NodeStatus status, Runnable healthCheck) {298 // Setting the Node as available if the initial call to status was successful.299 // Otherwise, retry to have it available as soon as possible.300 if (status.getAvailability() == UP) {301 updateNodeAvailability(status.getExternalUri(), status.getNodeId(), status.getAvailability());302 } else {303 // Running the health check right after the Node registers itself. We retry the304 // execution because the Node might on a complex network topology. For example,305 // Kubernetes pods with IPs that take a while before they are reachable.306 RetryPolicy<Object> initialHealthCheckPolicy = new RetryPolicy<>()307 .withMaxAttempts(-1)308 .withMaxDuration(Duration.ofSeconds(90))309 .withDelay(Duration.ofSeconds(15))310 .abortIf(result -> true);311 LOG.log(getDebugLogLevel(), "Running health check for Node " + status.getExternalUri());312 Executors.newSingleThreadExecutor().submit(313 () -> Failsafe.with(initialHealthCheckPolicy).run(healthCheck::run));314 }315 }316 private Runnable runNodeHealthChecks() {317 return () -> {318 ImmutableMap<NodeId, Runnable> nodeHealthChecks = ImmutableMap.copyOf(allChecks);319 for (Runnable nodeHealthCheck : nodeHealthChecks.values()) {320 GuardedRunnable.guard(nodeHealthCheck).run();321 }322 };323 }324 private Runnable asRunnableHealthCheck(Node node) {325 HealthCheck healthCheck = node.getHealthCheck();326 NodeId id = node.getId();327 return () -> {328 boolean checkFailed = false;329 Exception failedCheckException = null;330 LOG.log(getDebugLogLevel(), "Running health check for " + node.getUri());331 HealthCheck.Result result;332 try {333 result = healthCheck.check();334 } catch (Exception e) {335 LOG.log(Level.WARNING, "Unable to process node " + id, e);336 result = new HealthCheck.Result(DOWN, "Unable to run healthcheck. Assuming down");337 checkFailed = true;338 failedCheckException = e;339 }340 updateNodeAvailability(node.getUri(), id, result.getAvailability());341 if (checkFailed) {342 throw new HealthCheckFailedException("Node " + id, failedCheckException);343 }344 };345 }346 private void updateNodeAvailability(URI nodeUri, NodeId id, Availability availability) {347 Lock writeLock = lock.writeLock();348 writeLock.lock();349 try {350 LOG.log(351 getDebugLogLevel(),352 String.format("Health check result for %s was %s", nodeUri, availability));353 model.setAvailability(id, availability);354 model.updateHealthCheckCount(id, availability);355 } finally {356 writeLock.unlock();357 }358 }359 @Override360 public boolean drain(NodeId nodeId) {361 Node node = nodes.get(nodeId);362 if (node == null) {363 LOG.info("Asked to drain unregistered node " + nodeId);364 return false;365 }366 Lock writeLock = lock.writeLock();367 writeLock.lock();368 try {369 node.drain();370 model.setAvailability(nodeId, DRAINING);371 } finally {372 writeLock.unlock();373 }374 return node.isDraining();375 }376 public void remove(NodeId nodeId) {377 Lock writeLock = lock.writeLock();378 writeLock.lock();379 try {380 nodes.remove(nodeId);381 model.remove(nodeId);382 allChecks.remove(nodeId);383 } finally {384 writeLock.unlock();385 }386 }387 @Override388 public DistributorStatus getStatus() {389 Lock readLock = this.lock.readLock();390 readLock.lock();391 try {392 return new DistributorStatus(model.getSnapshot());393 } finally {394 readLock.unlock();395 }396 }397 @Beta398 public void refresh() {399 List<Runnable> allHealthChecks = new ArrayList<>();400 Lock readLock = this.lock.readLock();401 readLock.lock();402 try {403 allHealthChecks.addAll(allChecks.values());404 } finally {405 readLock.unlock();406 }407 allHealthChecks.parallelStream().forEach(Runnable::run);408 }409 protected Set<NodeStatus> getAvailableNodes() {410 Lock readLock = this.lock.readLock();411 readLock.lock();412 try {413 return model.getSnapshot().stream()414 .filter(node -> !DOWN.equals(node.getAvailability()))415 .collect(toImmutableSet());416 } finally {417 readLock.unlock();418 }419 }420 @Override421 public Either<SessionNotCreatedException, CreateSessionResponse> newSession(SessionRequest request)422 throws SessionNotCreatedException {423 Require.nonNull("Requests to process", request);424 Span span = tracer.getCurrentContext().createSpan("distributor.new_session");425 Map<String, EventAttributeValue> attributeMap = new HashMap<>();426 try {427 attributeMap.put(AttributeKey.LOGGER_CLASS.getKey(),428 EventAttribute.setValue(getClass().getName()));429 attributeMap.put("request.payload", EventAttribute.setValue(request.getDesiredCapabilities().toString()));430 String sessionReceivedMessage = "Session request received by the distributor";431 span.addEvent(sessionReceivedMessage, attributeMap);432 LOG.info(String.format("%s: \n %s", sessionReceivedMessage, request.getDesiredCapabilities()));433 // If there are no capabilities at all, something is horribly wrong434 if (request.getDesiredCapabilities().isEmpty()) {435 SessionNotCreatedException exception =436 new SessionNotCreatedException("No capabilities found in session request payload");437 EXCEPTION.accept(attributeMap, exception);438 attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),439 EventAttribute.setValue("Unable to create session. No capabilities found: " +440 exception.getMessage()));441 span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);442 return Either.left(exception);443 }444 boolean retry = false;445 SessionNotCreatedException lastFailure = new SessionNotCreatedException("Unable to create new session");446 for (Capabilities caps : request.getDesiredCapabilities()) {447 if (isNotSupported(caps)) {448 continue;449 }450 // Try and find a slot that we can use for this session. While we451 // are finding the slot, no other session can possibly be started.452 // Therefore, spend as little time as possible holding the write453 // lock, and release it as quickly as possible. Under no454 // circumstances should we try to actually start the session itself455 // in this next block of code.456 SlotId selectedSlot = reserveSlot(request.getRequestId(), caps);457 if (selectedSlot == null) {458 LOG.info(459 String.format("Unable to find a free slot for request %s. %s ",460 request.getRequestId(),461 caps));462 retry = true;463 continue;464 }465 CreateSessionRequest singleRequest = new CreateSessionRequest(466 request.getDownstreamDialects(),467 caps,468 request.getMetadata());469 try {470 CreateSessionResponse response = startSession(selectedSlot, singleRequest);471 sessions.add(response.getSession());472 model.setSession(selectedSlot, response.getSession());473 SessionId sessionId = response.getSession().getId();474 Capabilities sessionCaps = response.getSession().getCapabilities();475 String sessionUri = response.getSession().getUri().toString();476 SESSION_ID.accept(span, sessionId);477 CAPABILITIES.accept(span, sessionCaps);478 SESSION_ID_EVENT.accept(attributeMap, sessionId);479 CAPABILITIES_EVENT.accept(attributeMap, sessionCaps);480 span.setAttribute(SESSION_URI.getKey(), sessionUri);481 attributeMap.put(SESSION_URI.getKey(), EventAttribute.setValue(sessionUri));482 String sessionCreatedMessage = "Session created by the distributor";483 span.addEvent(sessionCreatedMessage, attributeMap);484 LOG.info(String.format("%s. Id: %s, Caps: %s", sessionCreatedMessage, sessionId, sessionCaps));485 return Either.right(response);486 } catch (SessionNotCreatedException e) {487 model.setSession(selectedSlot, null);488 lastFailure = e;489 }490 }491 // If we've made it this far, we've not been able to start a session492 if (retry) {493 lastFailure = new RetrySessionRequestException(494 "Will re-attempt to find a node which can run this session",495 lastFailure);496 attributeMap.put(497 AttributeKey.EXCEPTION_MESSAGE.getKey(),498 EventAttribute.setValue("Will retry session " + request.getRequestId()));499 } else {500 EXCEPTION.accept(attributeMap, lastFailure);501 attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),502 EventAttribute.setValue("Unable to create session: " + lastFailure.getMessage()));503 span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);504 }505 return Either.left(lastFailure);506 } catch (SessionNotCreatedException e) {507 span.setAttribute(AttributeKey.ERROR.getKey(), true);508 span.setStatus(Status.ABORTED);509 EXCEPTION.accept(attributeMap, e);510 attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),511 EventAttribute.setValue("Unable to create session: " + e.getMessage()));512 span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);513 return Either.left(e);514 } catch (UncheckedIOException e) {515 span.setAttribute(AttributeKey.ERROR.getKey(), true);516 span.setStatus(Status.UNKNOWN);517 EXCEPTION.accept(attributeMap, e);518 attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),519 EventAttribute.setValue("Unknown error in LocalDistributor while creating session: " + e.getMessage()));520 span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);521 return Either.left(new SessionNotCreatedException(e.getMessage(), e));522 } finally {523 span.close();524 }525 }526 private CreateSessionResponse startSession(SlotId selectedSlot, CreateSessionRequest singleRequest) {527 Node node = nodes.get(selectedSlot.getOwningNodeId());528 if (node == null) {529 throw new SessionNotCreatedException("Unable to find owning node for slot");530 }531 Either<WebDriverException, CreateSessionResponse> result;532 try {533 result = node.newSession(singleRequest);534 } catch (SessionNotCreatedException e) {535 result = Either.left(e);536 } catch (RuntimeException e) {537 result = Either.left(new SessionNotCreatedException(e.getMessage(), e));538 }539 if (result.isLeft()) {540 WebDriverException exception = result.left();541 if (exception instanceof SessionNotCreatedException) {542 throw exception;543 }544 throw new SessionNotCreatedException(exception.getMessage(), exception);545 }546 return result.right();547 }548 private SlotId reserveSlot(RequestId requestId, Capabilities caps) {549 Lock writeLock = lock.writeLock();550 writeLock.lock();551 try {552 Set<SlotId> slotIds = slotSelector.selectSlot(caps, getAvailableNodes());553 if (slotIds.isEmpty()) {554 LOG.log(555 getDebugLogLevel(),556 String.format("No slots found for request %s and capabilities %s", requestId, caps));557 return null;558 }559 for (SlotId slotId : slotIds) {560 if (reserve(slotId)) {561 return slotId;562 }563 }564 return null;565 } finally {566 writeLock.unlock();567 }568 }569 private boolean isNotSupported(Capabilities caps) {570 return getAvailableNodes().stream().noneMatch(node -> node.hasCapability(caps));571 }572 private boolean reserve(SlotId id) {573 Require.nonNull("Slot ID", id);574 Lock writeLock = this.lock.writeLock();575 writeLock.lock();576 try {577 Node node = nodes.get(id.getOwningNodeId());578 if (node == null) {579 LOG.log(getDebugLogLevel(), String.format("Unable to find node with id %s", id));580 return false;581 }582 return model.reserve(id);583 } finally {584 writeLock.unlock();585 }586 }587 @Override588 public void close() {589 LOG.info("Shutting down Distributor executor service");590 purgeDeadNodesService.shutdown();591 nodeHealthCheckService.shutdown();592 newSessionService.shutdown();593 }594 private class NewSessionRunnable implements Runnable {595 @Override596 public void run() {597 boolean loop = true;598 while (loop) {599 // We deliberately run this outside of a lock: if we're unsuccessful600 // starting the session, we just put the request back on the queue.601 // This does mean, however, that under high contention, we might end602 // up starving a session request.603 Set<Capabilities> stereotypes =604 getAvailableNodes()605 .stream()606 .filter(NodeStatus::hasCapacity)607 .map(608 node ->609 node610 .getSlots()611 .stream()612 .map(Slot::getStereotype)613 .collect(Collectors.toSet()))614 .flatMap(Collection::stream)615 .collect(Collectors.toSet());616 if (!stereotypes.isEmpty()) {617 Optional<SessionRequest> maybeRequest = sessionQueue.getNextAvailable(stereotypes);618 maybeRequest.ifPresent(619 req -> sessionCreatorExecutor.execute(() -> handleNewSessionRequest(req)));620 loop = maybeRequest.isPresent();621 } else {622 loop = false;623 }624 }625 if (rejectUnsupportedCaps) {626 checkMatchingSlot(sessionQueue.getQueueContents());627 }628 }629 private void checkMatchingSlot(List<SessionRequestCapability> sessionRequests) {630 for(SessionRequestCapability request : sessionRequests) {631 long unmatchableCount = request.getDesiredCapabilities().stream()632 .filter(LocalDistributor.this::isNotSupported)633 .count();634 if (unmatchableCount == request.getDesiredCapabilities().size()) {635 SessionNotCreatedException exception = new SessionNotCreatedException(636 "No nodes support the capabilities in the request");637 sessionQueue.complete(request.getRequestId(), Either.left(exception));638 }639 }640 }641 private void handleNewSessionRequest(SessionRequest sessionRequest) {642 RequestId reqId = sessionRequest.getRequestId();643 try (Span span = TraceSessionRequest.extract(tracer, sessionRequest).createSpan("distributor.poll_queue")) {644 Map<String, EventAttributeValue> attributeMap = new HashMap<>();645 attributeMap.put(646 AttributeKey.LOGGER_CLASS.getKey(),647 EventAttribute.setValue(getClass().getName()));648 span.setAttribute(AttributeKey.REQUEST_ID.getKey(), reqId.toString());649 attributeMap.put(650 AttributeKey.REQUEST_ID.getKey(),651 EventAttribute.setValue(reqId.toString()));652 attributeMap.put("request", EventAttribute.setValue(sessionRequest.toString()));653 Either<SessionNotCreatedException, CreateSessionResponse> response = newSession(sessionRequest);654 if (response.isLeft() && response.left() instanceof RetrySessionRequestException) {655 try(Span childSpan = span.createSpan("distributor.retry")) {656 LOG.log(Debug.getDebugLogLevel(),657 String.format("Retrying %s", sessionRequest.getDesiredCapabilities()));658 boolean retried = sessionQueue.retryAddToQueue(sessionRequest);659 attributeMap.put("request.retry_add", EventAttribute.setValue(retried));660 childSpan.addEvent("Retry adding to front of queue. No slot available.", attributeMap);661 if (retried) {662 return;663 }664 childSpan.addEvent("retrying_request", attributeMap);665 }666 }667 sessionQueue.complete(reqId, response);668 }669 }670 }...
Source:RemoteWebDriverBuilder.java
...54import java.util.logging.Logger;55import java.util.stream.Collectors;56import java.util.stream.StreamSupport;57import static java.util.logging.Level.WARNING;58import static org.openqa.selenium.internal.Debug.getDebugLogLevel;59import static org.openqa.selenium.remote.DriverCommand.QUIT;60import static org.openqa.selenium.remote.http.HttpMethod.DELETE;61/**62 * Create a new Selenium session using the W3C WebDriver protocol. This class will not generate any63 * data expected by the original JSON Wire Protocol, so will fail to create sessions as expected if64 * used against a server that only implements that protocol.65 * <p>66 * Expected usage is something like:67 * <pre>68 * WebDriver driver = RemoteWebDriver.builder()69 * .addAlternative(new FirefoxOptions())70 * .addAlternative(new ChromeOptions())71 * .addMetadata("cloud:key", "hunter2")72 * .setCapability("proxy", new Proxy())73 * .build();74 * </pre>75 * In this example, we ask for a session where the browser will be either Firefox or Chrome (we76 * don't care which), but where either browser will use the given {@link org.openqa.selenium.Proxy}.77 * In addition, we've added some metadata to the session, setting the "{@code cloud.key}" to be the78 * secret passphrase of our account with the cloud "Selenium as a Service" provider.79 * <p>80 * If no call to {@link #withDriverService(DriverService)} or {@link #address(URI)} is made, the81 * builder will use {@link ServiceLoader} to find all instances of {@link WebDriverInfo} and will82 * call {@link WebDriverInfo#createDriver(Capabilities)} for the first supported set of83 * capabilities.84 */85@Beta86public class RemoteWebDriverBuilder {87 private static final Logger LOG = Logger.getLogger(RemoteWebDriverBuilder.class.getName());88 private static final Set<String> ILLEGAL_METADATA_KEYS = ImmutableSet.of(89 "alwaysMatch",90 "capabilities",91 "desiredCapabilities",92 "firstMatch");93 private final List<Capabilities> requestedCapabilities = new ArrayList<>();94 private final Map<String, Object> additionalCapabilities = new TreeMap<>();95 private final Map<String, Object> metadata = new TreeMap<>();96 private Function<ClientConfig, HttpHandler> handlerFactory =97 config -> {98 HttpClient.Factory factory = HttpClient.Factory.createDefault();99 HttpClient client = factory.createClient(config);100 return client.with(101 next -> req -> {102 try {103 return client.execute(req);104 } finally {105 if (req.getMethod() == DELETE) {106 HttpSessionId.getSessionId(req.getUri()).ifPresent(id -> {107 if (("/session/" + id).equals(req.getUri())) {108 try {109 client.close();110 } catch (UncheckedIOException e) {111 LOG.log(WARNING, "Swallowing exception while closing http client", e);112 }113 factory.cleanupIdleClients();114 }115 });116 }117 }118 });119 };120 private ClientConfig clientConfig = ClientConfig.defaultConfig();121 private URI remoteHost = null;122 private DriverService driverService;123 private Credentials credentials = null;124 RemoteWebDriverBuilder() {125 // Access through RemoteWebDriver.builder126 }127 /**128 * Clears the current set of alternative browsers and instead sets the list of possible choices to129 * the arguments given to this method.130 */131 public RemoteWebDriverBuilder oneOf(Capabilities maybeThis, Capabilities... orOneOfThese) {132 Require.nonNull("Capabilities to use", maybeThis);133 if (!requestedCapabilities.isEmpty()) {134 LOG.log(getDebugLogLevel(), "Removing existing requested capabilities: " + requestedCapabilities);135 requestedCapabilities.clear();136 }137 addAlternative(maybeThis);138 for (Capabilities caps : orOneOfThese) {139 Require.nonNull("Capabilities to use", caps);140 addAlternative(caps);141 }142 return this;143 }144 /**145 * Add to the list of possible configurations that might be asked for. It is possible to ask for146 * more than one type of browser per session. For example, perhaps you have an extension that is147 * available for two different kinds of browser, and you'd like to test it).148 */149 public RemoteWebDriverBuilder addAlternative(Capabilities options) {150 Require.nonNull("Capabilities to use", options);151 requestedCapabilities.add(new ImmutableCapabilities(options));152 return this;153 }154 /**155 * Adds metadata to the outgoing new session request, which can be used by intermediary of end156 * nodes for any purpose they choose (commonly, this is used to request additional features from157 * cloud providers, such as video recordings or to set the timezone or screen size). Neither158 * parameter can be {@code null}.159 */160 public RemoteWebDriverBuilder addMetadata(String key, Object value) {161 Require.nonNull("Metadata key", key);162 Require.nonNull("Metadata value", value);163 if (ILLEGAL_METADATA_KEYS.contains(key)) {164 throw new IllegalArgumentException(String.format("Cannot add %s as metadata key", key));165 }166 Object previous = metadata.put(key, value);167 if (previous != null) {168 LOG.log(169 getDebugLogLevel(),170 String.format("Overwriting metadata %s. Previous value %s, new value %s", key, previous, value));171 }172 return this;173 }174 /**175 * Sets a capability for every single alternative when the session is created. These capabilities176 * are only set once the session is created, so this will be set on capabilities added via177 * {@link #addAlternative(Capabilities)} or {@link #oneOf(Capabilities, Capabilities...)} even178 * after this method call.179 */180 public RemoteWebDriverBuilder setCapability(String capabilityName, Object value) {181 Require.nonNull("Capability name", capabilityName);182 Require.nonNull("Capability value", value);183 Object previous = additionalCapabilities.put(capabilityName, value);184 if (previous != null) {185 LOG.log(186 getDebugLogLevel(),187 String.format("Overwriting capability %s. Previous value %s, new value %s", capabilityName, previous, value));188 }189 return this;190 }191 /**192 * @see #address(URI)193 */194 public RemoteWebDriverBuilder address(String uri) {195 Require.nonNull("Address", uri);196 try {197 return address(new URI(uri));198 } catch (URISyntaxException e) {199 throw new IllegalArgumentException("Unable to create URI from " + uri);200 }...
Source:Connection.java
...42import java.util.function.Consumer;43import java.util.logging.Level;44import java.util.logging.Logger;45import static java.util.concurrent.TimeUnit.MILLISECONDS;46import static org.openqa.selenium.internal.Debug.getDebugLogLevel;47import static org.openqa.selenium.json.Json.MAP_TYPE;48import static org.openqa.selenium.remote.http.HttpMethod.GET;49public class Connection implements Closeable {50 private static final Logger LOG = Logger.getLogger(Connection.class.getName());51 private static final Json JSON = new Json();52 private static final Executor EXECUTOR = Executors.newCachedThreadPool(r -> {53 Thread thread = new Thread(r, "CDP Connection");54 thread.setDaemon(true);55 return thread;56 });57 private static final AtomicLong NEXT_ID = new AtomicLong(1L);58 private final WebSocket socket;59 private final Map<Long, Consumer<Either<Throwable, JsonInput>>> methodCallbacks = new LinkedHashMap<>();60 private final Multimap<Event<?>, Consumer<?>> eventCallbacks = HashMultimap.create();61 public Connection(HttpClient client, String url) {62 Require.nonNull("HTTP client", client);63 Require.nonNull("URL to connect to", url);64 socket = client.openSocket(new HttpRequest(GET, url), new Listener());65 }66 private static class NamedConsumer<X> implements Consumer<X> {67 private final String name;68 private final Consumer<X> delegate;69 private NamedConsumer(String name, Consumer<X> delegate) {70 this.name = name;71 this.delegate = delegate;72 }73 public static <X> Consumer<X> of(String name, Consumer<X> delegate) {74 return new NamedConsumer<>(name, delegate);75 }76 @Override77 public void accept(X x) {78 delegate.accept(x);79 }80 @Override81 public String toString() {82 return "Consumer for " + name;83 }84 }85 public <X> CompletableFuture<X> send(SessionID sessionId, Command<X> command) {86 long id = NEXT_ID.getAndIncrement();87 CompletableFuture<X> result = new CompletableFuture<>();88 if (command.getSendsResponse()) {89 methodCallbacks.put(id, NamedConsumer.of(command.getMethod(), inputOrException -> {90 if (inputOrException.isRight()) {91 try {92 X value = command.getMapper().apply(inputOrException.right());93 result.complete(value);94 } catch (Throwable e) {95 LOG.log(Level.WARNING, String.format("Unable to map result for %s", command.getMethod()), e);96 result.completeExceptionally(e);97 }98 } else {99 result.completeExceptionally(inputOrException.left());100 }101 }));102 }103 ImmutableMap.Builder<String, Object> serialized = ImmutableMap.builder();104 serialized.put("id", id);105 serialized.put("method", command.getMethod());106 serialized.put("params", command.getParams());107 if (sessionId != null) {108 serialized.put("sessionId", sessionId);109 }110 StringBuilder json = new StringBuilder();111 try (JsonOutput out = JSON.newOutput(json).writeClassName(false)) {112 out.write(serialized.build());113 }114 LOG.log(getDebugLogLevel(), () -> String.format("-> %s", json));115 socket.sendText(json);116 if (!command.getSendsResponse() ) {117 result.complete(null);118 }119 return result;120 }121 public <X> X sendAndWait(SessionID sessionId, Command<X> command, Duration timeout) {122 try {123 CompletableFuture<X> future = send(sessionId, command);124 return future.get(timeout.toMillis(), MILLISECONDS);125 } catch (InterruptedException e) {126 Thread.currentThread().interrupt();127 throw new IllegalStateException("Thread has been interrupted", e);128 } catch (ExecutionException e) {129 Throwable cause = e;130 if (e.getCause() != null) {131 cause = e.getCause();132 }133 throw new DevToolsException(cause);134 } catch (TimeoutException e) {135 throw new org.openqa.selenium.TimeoutException(e);136 }137 }138 public <X> void addListener(Event<X> event, Consumer<X> handler) {139 Require.nonNull("Event to listen for", event);140 Require.nonNull("Handler to call", handler);141 synchronized (eventCallbacks) {142 eventCallbacks.put(event, handler);143 }144 }145 public void clearListeners() {146 synchronized (eventCallbacks) {147 eventCallbacks.clear();148 }149 }150 @Override151 public void close() {152 socket.close();153 }154 private class Listener implements WebSocket.Listener {155 @Override156 public void onText(CharSequence data) {157 EXECUTOR.execute(() -> {158 try {159 handle(data);160 } catch (Throwable t) {161 LOG.log(Level.WARNING, "Unable to process: " + data, t);162 throw new DevToolsException(t);163 }164 });165 }166 }167 private void handle(CharSequence data) {168 // It's kind of gross to decode the data twice, but this lets us get started on something169 // that feels nice to users.170 // TODO: decode once, and once only171 String asString = String.valueOf(data);172 LOG.log(getDebugLogLevel(), () -> String.format("<- %s", asString));173 Map<String, Object> raw = JSON.toType(asString, MAP_TYPE);174 if (raw.get("id") instanceof Number175 && (raw.get("result") != null || raw.get("error") != null)) {176 Consumer<Either<Throwable, JsonInput>> consumer = methodCallbacks.remove(((Number) raw.get("id")).longValue());177 if (consumer == null) {178 return;179 }180 try (StringReader reader = new StringReader(asString);181 JsonInput input = JSON.newInput(reader)) {182 input.beginObject();183 while (input.hasNext()) {184 switch (input.nextName()) {185 case "result":186 consumer.accept(Either.right(input));187 break;188 case "error":189 consumer.accept(Either.left(new WebDriverException(asString)));190 input.skipValue();191 break;192 default:193 input.skipValue();194 }195 }196 input.endObject();197 }198 } else if (raw.get("method") instanceof String && raw.get("params") instanceof Map) {199 LOG.log(200 getDebugLogLevel(),201 String.format("Method %s called with %d callbacks available", raw.get("method"), eventCallbacks.keySet().size()));202 synchronized (eventCallbacks) {203 // TODO: Also only decode once.204 eventCallbacks.keySet().stream()205 .peek(event -> LOG.log(206 getDebugLogLevel(),207 String.format("Matching %s with %s", raw.get("method"), event.getMethod())))208 .filter(event -> raw.get("method").equals(event.getMethod()))209 .forEach(event -> {210 // TODO: This is grossly inefficient. I apologise, and we should fix this.211 try (StringReader reader = new StringReader(asString);212 JsonInput input = JSON.newInput(reader)) {213 Object value = null;214 input.beginObject();215 while (input.hasNext()) {216 switch (input.nextName()) {217 case "params":218 value = event.getMapper().apply(input);219 break;220 default:221 input.skipValue();222 break;223 }224 }225 input.endObject();226 if (value == null) {227 // Do nothing.228 return;229 }230 final Object finalValue = value;231 for (Consumer<?> action : eventCallbacks.get(event)) {232 @SuppressWarnings("unchecked") Consumer<Object> obj = (Consumer<Object>) action;233 LOG.log(234 getDebugLogLevel(),235 String.format("Calling callback for %s using %s being passed %s", event, obj, finalValue));236 obj.accept(finalValue);237 }238 }239 });240 }241 } else {242 LOG.warning("Unhandled type: " + data);243 }244 }245}...
Source:RequestConverter.java
...51 @Override52 protected void channelRead0(53 ChannelHandlerContext ctx,54 HttpObject msg) throws Exception {55 LOG.log(Debug.getDebugLogLevel(), "Incoming message: " + msg);56 if (msg instanceof io.netty.handler.codec.http.HttpRequest) {57 LOG.log(Debug.getDebugLogLevel(), "Start of http request: " + msg);58 io.netty.handler.codec.http.HttpRequest nettyRequest =59 (io.netty.handler.codec.http.HttpRequest) msg;60 if (HttpUtil.is100ContinueExpected(nettyRequest)) {61 ctx.write(new HttpResponse().setStatus(100));62 return;63 }64 if (nettyRequest.headers().contains("Sec-WebSocket-Version") &&65 "upgrade".equals(nettyRequest.headers().get("Connection"))) {66 // Pass this on to later in the pipeline.67 ReferenceCountUtil.retain(msg);68 ctx.fireChannelRead(msg);69 return;70 }71 HttpRequest req = createRequest(ctx, nettyRequest);72 if (req == null) {73 return;74 }75 req.setAttribute(AttributeKey.HTTP_SCHEME.getKey(),76 nettyRequest.protocolVersion().protocolName());77 req.setAttribute(AttributeKey.HTTP_FLAVOR.getKey(),78 nettyRequest.protocolVersion().majorVersion());79 out = new PipedOutputStream();80 InputStream in = new PipedInputStream(out);81 req.setContent(memoize(() -> in));82 ctx.fireChannelRead(req);83 }84 if (msg instanceof HttpContent) {85 ByteBuf buf = ((HttpContent) msg).content().retain();86 EXECUTOR.submit(() -> {87 try (InputStream inputStream = new ByteBufInputStream(buf)) {88 ByteStreams.copy(inputStream, out);89 } catch (IOException e) {90 throw new UncheckedIOException(e);91 } finally {92 buf.release();93 }94 });95 }96 if (msg instanceof LastHttpContent) {97 LOG.log(Debug.getDebugLogLevel(), "Closing input pipe.");98 EXECUTOR.submit(() -> {99 try {100 out.close();101 } catch (IOException e) {102 throw new UncheckedIOException(e);103 }104 });105 }106 }107 private HttpRequest createRequest(108 ChannelHandlerContext ctx,109 io.netty.handler.codec.http.HttpRequest nettyRequest) {110 // Attempt to map the netty method111 HttpMethod method;112 if (nettyRequest.method().equals(HEAD)) {113 method = HttpMethod.GET;114 } else {115 try {116 method = HttpMethod.valueOf(nettyRequest.method().name());117 } catch (IllegalArgumentException e) {118 ctx.writeAndFlush(119 new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.METHOD_NOT_ALLOWED));120 return null;121 }122 }123 // Attempt to decode parameters124 try {125 QueryStringDecoder decoder = new QueryStringDecoder(nettyRequest.uri());126 HttpRequest req = new HttpRequest(127 method,128 decoder.path());129 decoder.parameters()130 .forEach((key, values) -> values.forEach(value -> req.addQueryParameter(key, value)));131 nettyRequest.headers().entries().stream()132 .filter(entry -> entry.getKey() != null)133 .forEach(entry -> req.addHeader(entry.getKey(), entry.getValue()));134 return req;135 } catch (Exception e) {136 ctx.writeAndFlush(137 new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));138 LOG.log(Debug.getDebugLogLevel(), "Not possible to decode parameters.", e);139 return null;140 }141 }142}...
Source:ProxyNodeCdp.java
...34import java.util.function.BiFunction;35import java.util.function.Consumer;36import java.util.logging.Level;37import java.util.logging.Logger;38import static org.openqa.selenium.internal.Debug.getDebugLogLevel;39import static org.openqa.selenium.remote.http.HttpMethod.GET;40public class ProxyNodeCdp implements BiFunction<String, Consumer<Message>, Optional<Consumer<Message>>> {41 private static final UrlTemplate CDP_TEMPLATE = new UrlTemplate("/session/{sessionId}/se/cdp");42 private static final Logger LOG = Logger.getLogger(ProxyNodeCdp.class.getName());43 private final HttpClient.Factory clientFactory;44 private final Node node;45 public ProxyNodeCdp(HttpClient.Factory clientFactory, Node node) {46 this.clientFactory = Objects.requireNonNull(clientFactory);47 this.node = Objects.requireNonNull(node);48 }49 @Override50 public Optional<Consumer<Message>> apply(String uri, Consumer<Message> downstream) {51 UrlTemplate.Match match = CDP_TEMPLATE.match(uri);52 if (match == null) {53 return Optional.empty();54 }55 LOG.fine("Matching CDP session for " + match.getParameters().get("sessionId"));56 SessionId id = new SessionId(match.getParameters().get("sessionId"));57 if (!node.isSessionOwner(id)) {58 LOG.info("Not owner of " + id);59 return Optional.empty();60 }61 Session session = node.getSession(id);62 Capabilities caps = session.getCapabilities();63 LOG.fine("Scanning for CDP endpoint: " + caps);64 // Using strings here to avoid Node depending upon specific drivers.65 Optional<URI> cdpUri = CdpEndpointFinder.getReportedUri("goog:chromeOptions", caps)66 .flatMap(reported -> CdpEndpointFinder.getCdpEndPoint(clientFactory, reported));67 if (cdpUri.isPresent()) {68 LOG.log(getDebugLogLevel(), "Chrome endpoint found");69 return cdpUri.map(cdp -> createCdpEndPoint(cdp, downstream));70 }71 cdpUri = CdpEndpointFinder.getReportedUri("moz:debuggerAddress", caps)72 .flatMap(reported -> CdpEndpointFinder.getCdpEndPoint(clientFactory, reported));73 if (cdpUri.isPresent()) {74 LOG.log(getDebugLogLevel(), "Firefox endpoint found");75 return cdpUri.map(cdp -> createCdpEndPoint(cdp, downstream));76 }77 LOG.fine("Searching for edge options");78 cdpUri = CdpEndpointFinder.getReportedUri("ms:edgeOptions", caps)79 .flatMap(reported -> CdpEndpointFinder.getCdpEndPoint(clientFactory, reported));80 if (cdpUri.isPresent()) {81 LOG.log(getDebugLogLevel(), "Edge endpoint found");82 }83 return cdpUri.map(cdp -> createCdpEndPoint(cdp, downstream));84 }85 private Consumer<Message> createCdpEndPoint(URI uri, Consumer<Message> downstream) {86 Objects.requireNonNull(uri);87 LOG.info("Establishing CDP connection to " + uri);88 HttpClient client = clientFactory.createClient(ClientConfig.defaultConfig().baseUri(uri));89 WebSocket upstream = client.openSocket(new HttpRequest(GET, uri.toString()), new ForwardingListener(downstream));90 return upstream::send;91 }92 private static class ForwardingListener implements WebSocket.Listener {93 private final Consumer<Message> downstream;94 public ForwardingListener(Consumer<Message> downstream) {95 this.downstream = Objects.requireNonNull(downstream);...
Source:DumpHttpExchangeFilter.java
...27public class DumpHttpExchangeFilter implements Filter {28 public static final Logger LOG = Logger.getLogger(DumpHttpExchangeFilter.class.getName());29 private final Level logLevel;30 public DumpHttpExchangeFilter() {31 this(Debug.getDebugLogLevel());32 }33 public DumpHttpExchangeFilter(Level logLevel) {34 this.logLevel = Require.nonNull("Log level", logLevel);35 }36 @Override37 public HttpHandler apply(HttpHandler next) {38 return req -> {39 // Use the supplier to avoid messing with the request unless we're logging40 LOG.log(logLevel, () -> requestLogMessage(req));41 HttpResponse res = next.execute(req);42 LOG.log(logLevel, () -> responseLogMessage(res));43 return res;44 };45 }...
Source:RetryRequest.java
...17package org.openqa.selenium.remote.http;18import static com.google.common.net.HttpHeaders.CONTENT_LENGTH;19import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;20import static java.net.HttpURLConnection.HTTP_UNAVAILABLE;21import static org.openqa.selenium.internal.Debug.getDebugLogLevel;22import net.jodah.failsafe.Failsafe;23import net.jodah.failsafe.RetryPolicy;24import org.openqa.selenium.TimeoutException;25import java.net.ConnectException;26import java.time.temporal.ChronoUnit;27import java.util.logging.Logger;28public class RetryRequest implements Filter {29 private static final Logger LOG = Logger.getLogger(RetryRequest.class.getName());30 // Retry on connection error.31 private static final RetryPolicy<HttpResponse> connectionFailurePolicy =32 new RetryPolicy<HttpResponse>()33 .handleIf(failure -> failure.getCause() instanceof ConnectException)34 .withBackoff(1, 4, ChronoUnit.SECONDS)35 .withMaxRetries(3)36 .onRetry(e -> LOG.log(37 getDebugLogLevel(),38 "Connection failure #{0}. Retrying.",39 e.getAttemptCount()));40 // Retry on read timeout.41 private static final RetryPolicy<HttpResponse> readTimeoutPolicy =42 new RetryPolicy<HttpResponse>()43 .handle(TimeoutException.class)44 .withBackoff(1, 4, ChronoUnit.SECONDS)45 .withMaxRetries(3)46 .onRetry(e -> LOG.log(47 getDebugLogLevel(),48 "Read timeout #{0}. Retrying.",49 e.getAttemptCount()));50 // Retry if server is unavailable or an internal server error occurs without response body.51 private static final RetryPolicy<HttpResponse> serverErrorPolicy =52 new RetryPolicy<HttpResponse>()53 .handleResultIf(response -> response.getStatus() == HTTP_INTERNAL_ERROR &&54 Integer.parseInt(response.getHeader(CONTENT_LENGTH)) == 0)55 .handleResultIf(response -> response.getStatus() == HTTP_UNAVAILABLE)56 .withBackoff(1, 2, ChronoUnit.SECONDS)57 .withMaxRetries(2)58 .onRetry(e -> LOG.log(59 getDebugLogLevel(),60 "Failure due to server error #{0}. Retrying.",61 e.getAttemptCount()));62 @Override63 public HttpHandler apply(HttpHandler next) {64 return req -> Failsafe.with(65 connectionFailurePolicy,66 readTimeoutPolicy,67 serverErrorPolicy)68 .get(() -> next.execute(req));69 }70}...
Source:Debug.java
...33 }34 public static boolean isDebugging() {35 return IS_DEBUG;36 }37 public static Level getDebugLogLevel() {38 return isDebugging() ? Level.INFO : Level.FINE;39 }40}...
getDebugLogLevel
Using AI Code Generation
1package com.test;2import org.openqa.selenium.internal.Debug;3public class SeleniumDebugLogLevel {4public static void main(String[] args) {5Debug debug = new Debug();6int logLevel = debug.getDebugLogLevel();7System.out.println("Current log level is " + logLevel);8}9}10Selenium WebDriver Debug Class - getDebugLogLevel() Method - Example 211package com.test;12import org.openqa.selenium.internal.Debug;13public class SeleniumDebugLogLevel {14public static void main(String[] args) {15Debug debug = new Debug();16debug.setDebugLogLevel(5);17int logLevel = debug.getDebugLogLevel();18System.out.println("Current log level is " + logLevel);19}20}21Selenium WebDriver Debug Class - getDebugLogLevel() Method - Example 322package com.test;23import org.openqa.selenium.internal.Debug;24public class SeleniumDebugLogLevel {25public static void main(String[] args) {26Debug debug = new Debug();27debug.setDebugLogLevel(5);28int logLevel = debug.getDebugLogLevel();29System.out.println("Current log level is " + logLevel);30}31}32Selenium WebDriver Debug Class - getDebugLogLevel() Method - Example 433package com.test;34import org.openqa.selenium.internal.Debug;35public class SeleniumDebugLogLevel {36public static void main(String[] args) {37Debug debug = new Debug();38debug.setDebugLogLevel(5);39int logLevel = debug.getDebugLogLevel();40System.out.println("Current log level is " + logLevel);41}42}43Selenium WebDriver Debug Class - getDebugLogLevel() Method - Example 544package com.test;45import org.openqa.selenium.internal.Debug;46public class SeleniumDebugLogLevel {47public static void main(String[] args) {48Debug debug = new Debug();49debug.setDebugLogLevel(5);
getDebugLogLevel
Using AI Code Generation
1import org.openqa.selenium.internal.Debug;2import org.openqa.selenium.internal.DebugLogLevel;3import java.io.File;4public class DebugTest {5 public static void main(String[] args) throws Exception {6 File file = new File("/tmp/selenium.log");7 file.createNewFile();8 Debug.setLogLevel(DebugLogLevel.INFO);9 Debug.setLogLevel(DebugLogLevel.DEBUG);10 Debug.setLogLevel(DebugLogLevel.OFF);11 if (Debug.getDebugLogLevel() == DebugLogLevel.OFF) {12 System.out.println("Log level is OFF");13 }14 }15}16Source Project: selenium Source File: Debug.java License: Apache License 2.0 5 votes /** * The debug log level. * * @author Simon Stewart */ public enum DebugLogLevel { OFF, INFO, DEBUG }17Source Project: selenium Source File: Debug.java License: Apache License 2.0 5 votes /** * The debug log level. * * @author Simon Stewart */ public enum DebugLogLevel { OFF, INFO, DEBUG }18Source Project: selenium Source File: Debug.java License: Apache License 2.0 5 votes /** * The debug log level. * * @author Simon Stewart */ public enum DebugLogLevel { OFF, INFO, DEBUG }19Source Project: selenium Source File: Debug.java License: Apache License 2.0 5 votes /** * The debug log level. * * @author Simon Stewart */ public enum DebugLogLevel { OFF, INFO, DEBUG }20Source Project: selenium Source File: Debug.java License: Apache License 2.0 5 votes /** * The debug log level. * * @author Simon Stewart */ public enum DebugLogLevel { OFF, INFO, DEBUG }
getDebugLogLevel
Using AI Code Generation
1Debug debug = new Debug();2debug.getDebugLogLevel()3Debug debug = new Debug();4debug.setDebugLogLevel("info")5Selenium | Debug class | setDebugLogLevel() Method6Selenium | Debug class | getDebugLogLevel() Method7Selenium | Debug class | getDebugFile() Method8Selenium | Debug class | setDebugFile() Method9Selenium | Debug class | setDebug() Method10Selenium | Debug class | getDebug() Method11Selenium | Debug class | isDebugEnabled() Method12Selenium | Debug class | setDebugMode() Method13Selenium | Debug class | getDebugMode() Method14Selenium | Debug class | setDebugMode() Method15Selenium | Debug class | getDebugMode() Method16Selenium | Debug class | getDebugFile() Method17Selenium | Debug class | setDebugFile() Method18Selenium | Debug class | getDebug() Method19Selenium | Debug class | setDebug() Method20Selenium | Debug class | isDebugEnabled() Method21Selenium | Debug class | getDebugLogLevel() Method
LambdaTest’s Selenium 4 tutorial is covering every aspects of Selenium 4 testing with examples and best practices. Here you will learn basics, such as how to upgrade from Selenium 3 to Selenium 4, to some advanced concepts, such as Relative locators and Selenium Grid 4 for Distributed testing. Also will learn new features of Selenium 4, such as capturing screenshots of specific elements, opening a new tab or window on the browser, and new protocol adoptions.
Upgrading From Selenium 3 To Selenium 4?: In this chapter, learn in detail how to update Selenium 3 to Selenium 4 for Java binding. Also, learn how to upgrade while using different build tools such as Maven or Gradle and get comprehensive guidance for upgrading Selenium.
What’s New In Selenium 4 & What’s Being Deprecated? : Get all information about new implementations in Selenium 4, such as W3S protocol adaption, Optimized Selenium Grid, and Enhanced Selenium IDE. Also, learn what is deprecated for Selenium 4, such as DesiredCapabilites and FindsBy methods, etc.
Selenium 4 With Python: Selenium supports all major languages, such as Python, C#, Ruby, and JavaScript. In this chapter, learn how to install Selenium 4 for Python and the features of Python in Selenium 4, such as Relative locators, Browser manipulation, and Chrom DevTool protocol.
Selenium 4 Is Now W3C Compliant: JSON Wireframe protocol is retiring from Selenium 4, and they are adopting W3C protocol to learn in detail about the advantages and impact of these changes.
How To Use Selenium 4 Relative Locator? : Selenium 4 came with new features such as Relative Locators that allow constructing locators with reference and easily located constructors nearby. Get to know its different use cases with examples.
Selenium Grid 4 Tutorial For Distributed Testing: Selenium Grid 4 allows you to perform tests over different browsers, OS, and device combinations. It also enables parallel execution browser testing, reads up on various features of Selenium Grid 4 and how to download it, and runs a test on Selenium Grid 4 with best practices.
Selenium Video Tutorials: Binge on video tutorials on Selenium by industry experts to get step-by-step direction from automating basic to complex test scenarios with Selenium.
LambdaTest also provides certification for Selenium testing to accelerate your career in Selenium automation testing.
Get 100 minutes of automation test minutes FREE!!