public void Operate(string testId, SessionStartInfo sessionStartInfo, TaskListener <RunningSession> listener) { Logger.Log(TraceLevel.Notice, testId, Stage.Open, new { sessionStartInfo.AgentSessionId }); Stopwatch stopwatch = Stopwatch.StartNew(); TaskListener <RunningSession> taskListener = new TaskListener <RunningSession>( (runningSession) => OnComplete_(sessionStartInfo, listener, runningSession, stopwatch, testId), (ex) => { var webEx = CommonUtils.GetInnerException <WebException>(ex); if (webEx != null && webEx.Status != WebExceptionStatus.Success) { CommonUtils.LogExceptionStackTrace(Logger, Stage.Open, ex, new { webExceptionStatus = webEx.Status }, testId); listener.OnFail(ex.InnerException); return; } OnFail_(stopwatch, sessionStartInfo, listener, testId); } ); try { ServerConnector.StartSession(taskListener, sessionStartInfo); } catch (Exception e) { listener.OnFail(e); } }
public virtual void PostDomCapture(TaskListener <string> listener, string domJson, params string[] testIds) { Logger.Log(TraceLevel.Info, testIds, Stage.Check, StageType.UploadStart); try { byte[] binData = Encoding.UTF8.GetBytes(domJson); Logger.Log(TraceLevel.Info, testIds, Stage.Check, StageType.UploadResource, new { UncompressedDataSize = binData.Length }); using (MemoryStream compressedStream = new MemoryStream()) { using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) { zipStream.Write(binData, 0, binData.Length); } binData = compressedStream.ToArray(); } Logger.Log(TraceLevel.Notice, testIds, Stage.Check, StageType.UploadResource, new { CompressedDataSize = binData.Length }); UploadData_(listener, binData, "application/octet-stream", "application/json", testIds); } catch (Exception ex) { CommonUtils.LogExceptionStackTrace(Logger, Stage.Check, StageType.UploadResource, ex, testIds); listener.OnFail(new EyesException($"PostDomSnapshot failed: {ex.Message}", ex)); } }
public void Operate(string testId, SessionStopInfo sessionStopInfo, TaskListener <TestResults> listener) { if (sessionStopInfo == null) { TestResults testResults = new TestResults(); testResults.Status = TestResultsStatus.NotOpened; listener.OnComplete(testResults); return; } TaskListener <TestResults> taskListener = new TaskListener <TestResults>( (testResults) => { Logger.Log(TraceLevel.Notice, testId, Stage.Close, new { testResults.Status }); testResults.IsNew = sessionStopInfo.RunningSession.IsNewSession; testResults.Url = sessionStopInfo.RunningSession.Url; Logger.Verbose(testResults.ToString()); testResults.ServerConnector = ServerConnector; listener.OnComplete(testResults); }, (ex) => { listener.OnFail(new EyesException("Failed closing test", ex)); }); try { Logger.Log(TraceLevel.Notice, testId, Stage.Close, new { sessionStopInfo }); ServerConnector.EndSession(taskListener, sessionStopInfo); } catch (Exception e) { listener.OnFail(e); } }
private void UploadData_(TaskListener <string> listener, byte[] bytes, string contentType, string mediaType, string[] testIds) { RenderingInfo renderingInfo = GetRenderingInfo(); string targetUrl = renderingInfo?.ResultsUrl?.AbsoluteUri; if (targetUrl == null) { listener.OnComplete(null); return; } Guid guid = Guid.NewGuid(); targetUrl = targetUrl.Replace("__random__", guid.ToString()); Logger.Log(TraceLevel.Info, testIds, Stage.General, StageType.UploadStart, new { mediaType, targetUrl }); HttpRequestMessage request = CreateHttpRequestMessageForUpload_(targetUrl, bytes, contentType, mediaType); httpClient_.SendAsyncRequest(new TaskListener <HttpResponseMessage>( response => { if (response == null) { throw new NullReferenceException("response is null"); } listener.OnComplete(targetUrl); }, ex => listener.OnFail(ex)), request, Logger, new BackoffProvider(2), TimeSpan.FromMinutes(2)); }
public virtual void CheckResourceStatus(TaskListener <bool?[]> taskListener, HashSet <string> testIds, string renderId, HashObject[] hashes) { renderId = renderId ?? "NONE"; HttpRequestMessage request = CreateUfgHttpWebRequest_($"/query/resources-exist?rg_render-id={renderId}", content: hashes); Logger.Log(TraceLevel.Info, testIds, Stage.ResourceCollection, StageType.CheckResource, new { hashes, renderId }); SendUFGAsyncRequest_(taskListener, request); }
protected virtual void SendUFGAsyncRequest_ <T>(TaskListener <T> taskListener, HttpRequestMessage request) where T : class { httpClient_.SendAsyncRequest(new TaskListener <HttpResponseMessage>( response => { if (response == null) { throw new NullReferenceException("response is null"); } taskListener.OnComplete(response.DeserializeBody <T>(true)); }, ex => taskListener.OnFail(ex)), request, Logger, new BackoffProvider()); }
public void MatchWindow(string testId, MatchWindowData data, TaskListener <MatchResult> listener) { try { Logger.Log(TraceLevel.Info, testId, Stage.Check, StageType.MatchStart, new { matchWindowData = data }); LoggingListener <MatchResult> loggingListener = new LoggingListener <MatchResult>(listener, Logger, testId); ServerConnector.MatchWindow(loggingListener, data, testId); } catch (Exception ex) { CommonUtils.LogExceptionStackTrace(Logger, Stage.Check, StageType.MatchComplete, ex, testId); listener.OnFail(ex); } }
public virtual void Render(TaskListener <List <RunningRender> > renderListener, IList <IRenderRequest> requests) { ArgumentGuard.NotNull(requests, nameof(requests)); string fullAgentId = AgentId; foreach (IRenderRequest renderRequest in requests) { renderRequest.AgentId = fullAgentId; Logger.Log(TraceLevel.Info, renderRequest.TestId, Stage.Render, new { renderRequest }); } HttpRequestMessage request = CreateUfgHttpWebRequest_("render", content: requests); SendUFGAsyncRequest_(renderListener, request); }
protected virtual void StartSessionInternal(TaskListener <RunningSession> taskListener, SessionStartInfo startInfo) { ArgumentGuard.NotNull(startInfo, nameof(startInfo)); var body = new { StartInfo = startInfo }; try { EnsureHttpClient_(); httpClient_.PostJson( new TaskListener <HttpResponseMessage>( response => { if (response == null) { throw new NullReferenceException("response is null"); } // response.DeserializeBody disposes the response object's stream, // rendering all of its properties unusable, including StatusCode. HttpStatusCode responseStatusCode = response.StatusCode; RunningSession runningSession; if (responseStatusCode == HttpStatusCode.ServiceUnavailable) { runningSession = new RunningSession(); runningSession.ConcurrencyFull = true; } else { runningSession = response.DeserializeBody <RunningSession>( true, serializer_, HttpStatusCode.OK, HttpStatusCode.Created); if (runningSession.isNewSession_ == null) { runningSession.isNewSession_ = responseStatusCode == HttpStatusCode.Created; } runningSession.ConcurrencyFull = false; } taskListener.OnComplete(runningSession); }, ex => taskListener.OnFail(ex)) , "api/sessions/running", body); } catch (Exception ex) { throw new EyesException($"StartSession failed: {ex.Message}", ex); } }
private void OnFail_(Stopwatch stopwatch, SessionStartInfo sessionStartInfo, TaskListener <RunningSession> listener, string testId) { TimeSpan sleepDuration = TimeSpan.FromSeconds(2); if (stopwatch.Elapsed > TIME_TO_WAIT_FOR_OPEN) { isServerConcurrencyLimitReached_ = false; listener.OnFail(new EyesException("Timeout in start session")); return; } try { Thread.Sleep(sleepDuration); if (stopwatch.Elapsed.TotalSeconds >= 30) { sleepDuration = TimeSpan.FromSeconds(10); } else if (stopwatch.Elapsed.TotalSeconds >= 10) { sleepDuration = TimeSpan.FromSeconds(5); } Logger.Verbose("Trying startSession again"); ServerConnector.StartSession( new TaskListener <RunningSession>( (runningSession) => OnComplete_(sessionStartInfo, listener, runningSession, stopwatch, testId), (ex) => { var socketEx = CommonUtils.GetInnerException <SocketException>(ex); if (socketEx != null && socketEx.SocketErrorCode == SocketError.ConnectionRefused) { listener.OnFail(ex.InnerException); return; } OnFail_(stopwatch, sessionStartInfo, listener, testId); } ), sessionStartInfo); } catch (Exception e) { CommonUtils.LogExceptionStackTrace(Logger, Stage.Open, StageType.Retry, e, testId); listener.OnFail(e); } }
protected virtual void EndSessionInternal(TaskListener <TestResults> taskListener, SessionStopInfo sessionStopInfo) { ArgumentGuard.NotNull(sessionStopInfo, nameof(sessionStopInfo)); ArgumentGuard.NotNull(sessionStopInfo.RunningSession, nameof(sessionStopInfo.RunningSession)); httpClient_.DeleteJson(new TaskListener <HttpResponseMessage>( response => { if (response == null) { throw new NullReferenceException("response is null"); } taskListener.OnComplete(response.DeserializeBody <TestResults>(true)); }, ex => taskListener.OnFail(ex) ), $"api/sessions/running/{sessionStopInfo.RunningSession.Id}", sessionStopInfo); }
public virtual void RenderStatusById(TaskListener <List <RenderStatusResults> > taskListener, IList <string> testIds, IList <string> renderIds) { ArgumentGuard.NotNull(renderIds, nameof(renderIds)); ArgumentGuard.NotNull(testIds, nameof(testIds)); for (int i = 0; i < testIds.Count; i++) { Logger.Log(TraceLevel.Info, testIds[i], Stage.Render, StageType.RenderStatus, new { renderId = renderIds[i] }); } HttpRequestMessage request = CreateUfgHttpWebRequest_("render-status", content: renderIds); // request.Timeout = 1000; SendUFGAsyncRequest_(taskListener, request); }
private void OnComplete_(SessionStartInfo sessionStartInfo, TaskListener <RunningSession> listener, RunningSession runningSession, Stopwatch stopwatch, string testId) { if (runningSession.ConcurrencyFull) { isServerConcurrencyLimitReached_ = true; Logger.Log(TraceLevel.Warn, testId, Stage.Open, StageType.Retry, new { message = "Failed starting test, concurrency is fully used. Trying again." }); OnFail_(stopwatch, sessionStartInfo, listener, testId); return; } isServerConcurrencyLimitReached_ = false; Logger.Log(TraceLevel.Notice, testId, Stage.Open, StageType.Complete, new { message = $"Server session ID is {runningSession.Id}" }); //Logger.SessionId(runningSession.SessionId); listener.OnComplete(runningSession); }
public void TryUploadImage(string testId, MatchWindowData data, TaskListener taskListener) { AppOutput appOutput = data.AppOutput; if (appOutput.ScreenshotUrl != null) { taskListener.OnComplete(); return; } // Getting the screenshot bytes TaskListener <string> uploadListener = new TaskListener <string>( (url) => { if (url == null) { Logger.Verbose("Got null url from upload. Test id: {0}", testId); appOutput.ScreenshotUrl = null; taskListener.OnFail(new EyesException("Failed uploading image")); return; } Logger.Log(TraceLevel.Info, testId, Stage.Check, StageType.UploadComplete, new { url }); appOutput.ScreenshotUrl = url; appOutput.ClearScreenshotBytes(); taskListener.OnComplete(); }, (ex) => { appOutput.ScreenshotUrl = null; taskListener.OnFail(new EyesException("Failed uploading image", ex)); } ); try { Logger.Log(TraceLevel.Info, testId, Stage.Check, StageType.UploadStart, new { dataLength = appOutput.ScreenshotBytes.Length }); ServerConnector.UploadImage(uploadListener, appOutput.ScreenshotBytes, testId); } catch (Exception ex) { taskListener.OnFail(ex); } }
public void RenderPutResource(TaskListener <HttpResponseMessage> listener, string renderId, IVGResource resource) { ArgumentGuard.NotNull(resource, nameof(resource)); byte[] content = resource.Content; ArgumentGuard.NotNull(content, nameof(resource.Content)); string hash = resource.Sha256; string contentType = resource.ContentType?.Split(';')[0]; Logger.Log(TraceLevel.Info, resource.TestIds, Stage.Render, new { resourceHash = hash, resourceUrl = resource.Url, renderId }); HttpRequestMessage request = CreateUfgHttpWebRequest_($"/resources/sha256/{hash}?render-id={renderId}", method: "PUT", contentType: contentType, mediaType: contentType ?? "application/octet-stream", content: content); httpClient_.SendAsyncRequest(listener, request, Logger, new BackoffProvider()); Logger.Verbose("future created."); }
protected virtual void MatchWindowImpl_(TaskListener <MatchResult> listener, MatchWindowData data, string[] testIds) { string url = string.Format("api/sessions/running/{0}", data.RunningSession.Id); Logger.Log(TraceLevel.Notice, testIds, Stage.Check, StageType.MatchStart); httpClient_.PostJson(new TaskListener <HttpResponseMessage>( response => { Logger.Log(TraceLevel.Notice, testIds, Stage.Check, StageType.MatchComplete, new { response?.StatusCode }); if (response == null) { throw new NullReferenceException("response is null"); } MatchResult matchResult = response.DeserializeBody <MatchResult>(true); Logger.Log(TraceLevel.Info, testIds, Stage.Check, StageType.MatchComplete, new { matchResult }); listener.OnComplete(matchResult); }, e => listener.OnFail(e) ), url, data); }
public void MatchWindow(TaskListener <MatchResult> listener, MatchWindowData data, params string[] testIds) { ArgumentGuard.NotNull(data, nameof(data)); if (data.AppOutput.ScreenshotBytes != null) { UploadImage(new TaskListener <string>( returnedUrl => { Logger.Log(TraceLevel.Notice, testIds, Stage.General, StageType.UploadComplete, new { returnedUrl }); if (returnedUrl == null) { listener.OnFail(new EyesException($"{nameof(MatchWindow)} failed: could not upload image to storage service.")); return; } try { data.AppOutput.ScreenshotUrl = returnedUrl; MatchWindowImpl_(listener, data, testIds); } catch (Exception ex) { throw new EyesException($"{nameof(MatchWindow)} failed: {ex.Message}", ex); } }, ex => listener.OnFail(ex) ), data.AppOutput.ScreenshotBytes, testIds); } else if (data.AppOutput.ScreenshotUrl != null) { MatchWindowImpl_(listener, data, testIds); } else { throw new EyesException("Failed to upload image."); } }
public virtual void GetJobInfo(TaskListener <IList <JobInfo> > listener, IList <IRenderRequest> renderRequests) { ArgumentGuard.NotNull(renderRequests, nameof(renderRequests)); string[] testIds = renderRequests.Select(bi => bi.TestId).ToArray(); Logger.Log(TraceLevel.Notice, testIds, Stage.Open, StageType.JobInfo, new { renderRequests }); try { HttpRequestMessage request = CreateUfgHttpWebRequest_("job-info", content: renderRequests); Logger.Log(TraceLevel.Info, testIds, Stage.Open, StageType.RequestSent, new { request.RequestUri }); httpClient_.SendAsyncRequest(new TaskListener <HttpResponseMessage>( response => { JObject[] jobInfosUnparsed = response.DeserializeBody <JObject[]>(true); List <JobInfo> jobInfos = new List <JobInfo>(); foreach (JObject jobInfoUnparsed in jobInfosUnparsed) { JobInfo jobInfo = new JobInfo { Renderer = jobInfoUnparsed.Value <string>("renderer"), EyesEnvironment = jobInfoUnparsed.Value <object>("eyesEnvironment") }; jobInfos.Add(jobInfo); } Logger.Log(TraceLevel.Info, testIds, Stage.Open, StageType.RequestCompleted, new { request.RequestUri }); listener.OnComplete(jobInfos); }, ex => listener.OnFail(ex) ), request, Logger, new BackoffProvider()); } catch (Exception e) { CommonUtils.LogExceptionStackTrace(Logger, Stage.Open, StageType.JobInfo, e, testIds); listener.OnFail(e); } }
/// <summary> /// Starts a new session. /// </summary> public void StartSession(TaskListener <RunningSession> taskListener, SessionStartInfo sessionStartInfo) { StartSessionInternal(taskListener, sessionStartInfo); }
public override void Run() { while (inputQueue_.Count > 0) { Tuple <string, MatchWindowData> nextInput = inputQueue_.Dequeue(); string id = nextInput.Item1; lock (lockObject_) inUploadProcess_.Add(id); MatchWindowData matchWindowData = nextInput.Item2; TryUploadImage(id, matchWindowData, new TaskListener( () => { lock (lockObject_) { inUploadProcess_.Remove(id); matchWindowQueue_.Enqueue(Tuple.Create(id, matchWindowData)); } }, (e) => { lock (lockObject_) { inUploadProcess_.Remove(id); Logger.Log(TraceLevel.Error, id, Stage.Check, StageType.UploadComplete, new { nextInput }); errorQueue_.Add(Tuple.Create(id, e)); } })); } while (matchWindowQueue_.Count > 0) { Tuple <string, MatchWindowData> nextInput = matchWindowQueue_.Dequeue(); string id = nextInput.Item1; lock (lockObject_) inMatchWindowProcess_.Add(id); MatchWindowData matchWindowData = nextInput.Item2; TaskListener <MatchResult> listener = new TaskListener <MatchResult>( (taskResponse) => { lock (lockObject_) { inMatchWindowProcess_.Remove(id); outputQueue_.Add(Tuple.Create(id, taskResponse)); } }, (e) => { lock (lockObject_) { inMatchWindowProcess_.Remove(id); Logger.Log(TraceLevel.Error, id, Stage.Check, StageType.MatchComplete, new { nextInput }); errorQueue_.Add(new Tuple <string, Exception>(id, new EyesException("Match window failed"))); } }); try { MatchWindow(id, matchWindowData, listener); } catch (Exception ex) { CommonUtils.LogExceptionStackTrace(Logger, Stage.Check, StageType.MatchStart, ex, id); listener.OnFail(ex); } } ; }
/// <summary> /// Ends the input running session. /// </summary> public void EndSession(TaskListener <TestResults> taskListener, SessionStopInfo sessionStopInfo) { EndSessionInternal(taskListener, sessionStopInfo); }
public LoggingListener(TaskListener <T> internalListener, Logger logger, string message, [CallerMemberName] string caller = null, params string[] testIds) : this(internalListener.OnComplete, internalListener.OnFail, logger, caller, message, testIds) { }
public void UploadImage(TaskListener <string> listener, byte[] screenshotBytes, string[] testIds) { UploadData_(listener, screenshotBytes, "image/png", "image/png", testIds); }