public ServiceProxyProvider(string serviceName, IEventPublisher <ClientCallEvent> eventPublisher, ICertificateLocator certificateLocator, ILog log, Func <string, ReachabilityCheck, IMultiEnvironmentServiceDiscovery> serviceDiscoveryFactory, Func <DiscoveryConfig> getConfig, JsonExceptionSerializer exceptionSerializer) { EventPublisher = eventPublisher; CertificateLocator = certificateLocator; Log = log; ServiceName = serviceName; GetDiscoveryConfig = getConfig; ExceptionSerializer = exceptionSerializer; var metricsContext = Metric.Context(METRICS_CONTEXT_NAME).Context(ServiceName); _serializationTime = metricsContext.Timer("Serialization", Unit.Calls); _deserializationTime = metricsContext.Timer("Deserialization", Unit.Calls); _roundtripTime = metricsContext.Timer("Roundtrip", Unit.Calls); _successCounter = metricsContext.Counter("Success", Unit.Calls); _failureCounter = metricsContext.Counter("Failed", Unit.Calls); _hostFailureCounter = metricsContext.Counter("HostFailure", Unit.Calls); _applicationExceptionCounter = metricsContext.Counter("ApplicationException", Unit.Calls); ServiceDiscovery = serviceDiscoveryFactory(serviceName, ValidateReachability); }
public HttpServiceListener(IActivator activator, IWorker worker, IServiceEndPointDefinition serviceEndPointDefinition, ICertificateLocator certificateLocator, ILog log, IEventPublisher <ServiceCallEvent> eventPublisher, IEnumerable <ICustomEndpoint> customEndpoints, JsonExceptionSerializer exceptionSerializer, ServiceSchema serviceSchema, Func <LoadShedding> loadSheddingConfig, IServerRequestPublisher serverRequestPublisher) { ServiceSchema = serviceSchema; _serverRequestPublisher = serverRequestPublisher; ServiceEndPointDefinition = serviceEndPointDefinition; Worker = worker; Activator = activator; Log = log; EventPublisher = eventPublisher; CustomEndpoints = customEndpoints.ToArray(); ExceptionSerializer = exceptionSerializer; LoadSheddingConfig = loadSheddingConfig; if (serviceEndPointDefinition.UseSecureChannel) { ServerRootCertHash = certificateLocator.GetCertificate("Service").GetHashOfRootCertificate(); } var urlPrefixTemplate = ServiceEndPointDefinition.UseSecureChannel ? "https://+:{0}/" : "http://+:{0}/"; Prefix = string.Format(urlPrefixTemplate, ServiceEndPointDefinition.HttpPort); Listener = new HttpListener { IgnoreWriteExceptions = true, Prefixes = { Prefix } }; }
public HttpServiceListener( IActivator activator, IWorker worker, IServiceEndPointDefinition serviceEndPointDefinition, ICertificateLocator certificateLocator, ILog log, IEnumerable <ICustomEndpoint> customEndpoints, IEnvironment environment, JsonExceptionSerializer exceptionSerializer, ServiceSchema serviceSchema, Func <LoadShedding> loadSheddingConfig, IServerRequestPublisher serverRequestPublisher, CurrentApplicationInfo appInfo) { ServiceSchema = serviceSchema; _serverRequestPublisher = serverRequestPublisher; ServiceEndPointDefinition = serviceEndPointDefinition; Worker = worker; Activator = activator; Log = log; CustomEndpoints = customEndpoints.ToArray(); Environment = environment; ExceptionSerializer = exceptionSerializer; LoadSheddingConfig = loadSheddingConfig; AppInfo = appInfo; if (ServiceEndPointDefinition.HttpsPort != null && ServiceEndPointDefinition.ClientCertificateVerification != ClientCertificateVerificationMode.Disable) { ServerRootCertHash = certificateLocator.GetCertificate("Service").GetHashOfRootCertificate(); } Listener = new HttpListener { IgnoreWriteExceptions = true }; if (ServiceEndPointDefinition.HttpsPort != null) { Listener.Prefixes.Add($"https://+:{ServiceEndPointDefinition.HttpsPort}/"); } if (ServiceEndPointDefinition.HttpPort != null) { Listener.Prefixes.Add($"http://+:{ServiceEndPointDefinition.HttpPort}/"); } if (!Listener.Prefixes.Any()) { Log.Warn(_ => _("HttpServiceListener is not listening on any ports, no HTTP or HTTPS ports in ServiceEndPointDefinition")); } var context = Metric.Context("Service").Context(AppInfo.Name); _serializationTime = context.Timer("Serialization", Unit.Calls); _deserializationTime = context.Timer("Deserialization", Unit.Calls); _roundtripTime = context.Timer("Roundtrip", Unit.Calls); _metaEndpointsRoundtripTime = context.Timer("MetaRoundtrip", Unit.Calls); _successCounter = context.Counter("Success", Unit.Calls); _failureCounter = context.Counter("Failed", Unit.Calls); _activeRequestsCounter = context.Timer("ActiveRequests", Unit.Requests); _endpointContext = context.Context("Endpoints"); }
public virtual void SetUp() { TracingContext.SetUpStorage(); unitTesting = new TestingKernel <ConsoleLog>(mockConfig: MockConfig); Metric.ShutdownContext(ServiceProxyProvider.METRICS_CONTEXT_NAME); TracingContext.SetRequestID("1"); ExceptionSerializer = unitTesting.Get <JsonExceptionSerializer>(); }
public async Task RequestWithException_ShouldWrapWithUnhandledException() { _testinghost.Instance.When(a => a.DoSomething()).Throw(x => new ArgumentException("MyEx")); var request = await GetRequestFor <IDemoService>(p => p.DoSomething()); var responseJson = await(await new HttpClient().SendAsync(request)).Content.ReadAsStringAsync(); var responseException = JsonExceptionSerializer.Deserialize(responseJson); responseException.ShouldBeOfType <UnhandledException>(); }
public async Task RequestWithException_ShouldNotWrap(Type exceptionType) { _testinghost.Instance.When(a => a.DoSomething()).Throw(i => (Exception)Activator.CreateInstance(exceptionType, "MyEx", null, null, null)); var request = await GetRequestFor <IDemoService>(p => p.DoSomething()); var responseJson = await(await new HttpClient().SendAsync(request)).Content.ReadAsStringAsync(); var responseException = JsonExceptionSerializer.Deserialize(responseJson); responseException.ShouldBeOfType(exceptionType); }
public void RequestException_RoundTrip_IsIdentical() { var expected = new RequestException("message").ThrowAndCatch(); var json = JsonExceptionSerializer.Serialize(expected); var actual = JsonExceptionSerializer.Deserialize(json); actual.ShouldBeOfType <RequestException>(); actual.Message.ShouldBe(expected.Message); actual.StackTrace.ShouldBe(expected.StackTrace); }
public virtual void SetUp() { _insecureClient = _kernel.Get <IDemoService>(); _exceptionSerializer = _kernel.Get <JsonExceptionSerializer>(); Metric.ShutdownContext("Service"); TracingContext.SetUpStorage(); TracingContext.SetRequestID("1"); _testinghost = new TestingHost <IDemoService>(); _stopTask = _testinghost.RunAsync(new ServiceArguments(ServiceStartupMode.CommandLineNonInteractive)); }
public ClientConfiguration(BoltOptions options = null) { Options = options ?? new BoltOptions(); Serializer = new JsonSerializer(); ExceptionSerializer = new JsonExceptionSerializer(); EndpointProvider = new EndpointProvider(Options); SessionHandler = new ClientSessionHandler(Options); ProxyFactory = new ProxyFactory(); ErrorProvider = new ClientErrorProvider(Options.ServerErrorHeader); ErrorHandling = new ErrorHandling(); HttpMessageHandler = new HttpClientHandler(); }
public void HttpRequestException_RoundTrip_ReturnsSubstitue() { var ex = new HttpRequestException("message").ThrowAndCatch(); var json = JsonExceptionSerializer.Serialize(ex); var actual = JsonExceptionSerializer.Deserialize(json); var envException = actual.ShouldBeOfType <EnvironmentException>(); envException.RawMessage().ShouldEndWith(ex.RawMessage()); envException.UnencryptedTags["originalStackTrace"].ShouldBe(ex.StackTrace); }
public virtual void SetUp() { var kernel = new TestingKernel<ConsoleLog>(); _insecureClient = kernel.Get<IDemoService>(); _exceptionSerializer = kernel.Get<JsonExceptionSerializer>(); Metric.ShutdownContext("Service"); TracingContext.SetUpStorage(); TracingContext.SetRequestID("1"); _testinghost = new TestingHost<IDemoService>(); _stopTask = _testinghost.RunAsync(); }
public override void OneTimeSetUp() { base.OneTimeSetUp(); ExceptionSerializer = _unitTestingKernel.Get <JsonExceptionSerializer>(); Task t = ChangeConfig <StackTraceEnhancerSettings>(new[] { new KeyValuePair <string, string>("StackTraceEnhancerSettings.RegexReplacements.TidyAsyncLocalFunctionNames.Pattern", @"\.<>c__DisplayClass(?:\d+)_(?:\d+)(?:`\d)?\.<<(\w+)>g__(\w+)\|?\d>d.MoveNext\(\)"), new KeyValuePair <string, string>("StackTraceEnhancerSettings.RegexReplacements.TidyAsyncLocalFunctionNames.Replacement", @".$1.$2(async)") }); t.Wait(); }
public HttpServiceListener(IActivator activator, IWorker worker, IServiceEndPointDefinition serviceEndPointDefinition, ICertificateLocator certificateLocator, ILog log, IEnumerable <ICustomEndpoint> customEndpoints, IEnvironment environment, JsonExceptionSerializer exceptionSerializer, ServiceSchema serviceSchema, Func <LoadShedding> loadSheddingConfig, IServerRequestPublisher serverRequestPublisher, CurrentApplicationInfo appInfo ) { ServiceSchema = serviceSchema; _serverRequestPublisher = serverRequestPublisher; ServiceEndPointDefinition = serviceEndPointDefinition; Worker = worker; Activator = activator; Log = log; CustomEndpoints = customEndpoints.ToArray(); Environment = environment; ExceptionSerializer = exceptionSerializer; LoadSheddingConfig = loadSheddingConfig; AppInfo = appInfo; if (serviceEndPointDefinition.UseSecureChannel) { ServerRootCertHash = certificateLocator.GetCertificate("Service").GetHashOfRootCertificate(); } var urlPrefixTemplate = ServiceEndPointDefinition.UseSecureChannel ? "https://+:{0}/" : "http://+:{0}/"; Prefix = string.Format(urlPrefixTemplate, ServiceEndPointDefinition.HttpPort); Listener = new HttpListener { IgnoreWriteExceptions = true, Prefixes = { Prefix } }; var context = Metric.Context("Service").Context(AppInfo.Name); _serializationTime = context.Timer("Serialization", Unit.Calls); _deserializationTime = context.Timer("Deserialization", Unit.Calls); _roundtripTime = context.Timer("Roundtrip", Unit.Calls); _metaEndpointsRoundtripTime = context.Timer("MetaRoundtrip", Unit.Calls); _successCounter = context.Counter("Success", Unit.Calls); _failureCounter = context.Counter("Failed", Unit.Calls); _activeRequestsCounter = context.Timer("ActiveRequests", Unit.Requests); _endpointContext = context.Context("Endpoints"); }
public static HttpResponseMessage GetResponseWithException(Exception ex, HttpStatusCode?statusCode = null, bool withGigyaHostHeader = true) { var resMessage = new HttpResponseMessage { StatusCode = statusCode ?? HttpServiceListener.GetExceptionStatusCode(ex) }; if (withGigyaHostHeader) { resMessage.Headers.Add(GigyaHttpHeaders.ServerHostname, "host"); } resMessage.Content = new StringContent(JsonExceptionSerializer.Serialize(ex)); return(resMessage); }
public void InnerHttpRequestException_RoundTrip_IsStripped() { var webEx = new WebException("Web exception").ThrowAndCatch(); var httpEx = new HttpRequestException("HTTP request exception", webEx).ThrowAndCatch(); var ex = new RemoteServiceException("Remote service exception", "http://foo/bar", httpEx).ThrowAndCatch(); string json = JsonExceptionSerializer.Serialize(ex); var actual = JsonExceptionSerializer.Deserialize(json); actual.ShouldBeOfType <RemoteServiceException>(); actual.Message.ShouldBe(ex.Message); actual.StackTrace.ShouldBe(ex.StackTrace); actual.InnerException.ShouldBeOfType <WebException>(); actual.InnerException.Message.ShouldBe(webEx.Message); actual.InnerException.StackTrace.ShouldBe(webEx.StackTrace); }
public ServiceProxyProvider(string serviceName, IEventPublisher <ClientCallEvent> eventPublisher, ICertificateLocator certificateLocator, ILog log, Func <string, ReachabilityChecker, IServiceDiscovery> serviceDiscoveryFactory, Func <DiscoveryConfig> getConfig, JsonExceptionSerializer exceptionSerializer) { EventPublisher = eventPublisher; CertificateLocator = certificateLocator; Log = log; ServiceName = serviceName; GetDiscoveryConfig = getConfig; ExceptionSerializer = exceptionSerializer; ServiceDiscovery = serviceDiscoveryFactory(serviceName, IsReachable); }
public void SetUp() { var unitTesting = new TestingKernel <ConsoleLog>(k => k.Rebind <Func <StackTraceEnhancerSettings> >().ToConstant <Func <StackTraceEnhancerSettings> >(() => new StackTraceEnhancerSettings { RegexReplacements = new Dictionary <string, RegexReplace> { ["TidyAsyncLocalFunctionNames"] = new RegexReplace { Pattern = @"\.<>c__DisplayClass(?:\d+)_(?:\d+)(?:`\d)?\.<<(\w+)>g__(\w+)\|?\d>d.MoveNext\(\)", Replacement = @".$1.$2(async)" } } }) ); ExceptionSerializer = unitTesting.Get <JsonExceptionSerializer>(); }
public void ExceptionTypeNotAvailable_RoundTrip_FallsBackToAvailableType() { var expected = new MyException(30000, "message") { MyNumber = 42 }.ThrowAndCatch(); var json = JsonExceptionSerializer.Serialize(expected); json = json.Replace("MyException", "MyNonexistentException"); var actual = (RequestException)JsonExceptionSerializer.Deserialize(json); actual.ShouldBeOfType <RequestException>(); actual.Message.ShouldBe(expected.Message); actual.ErrorCode.ShouldBe(30000); actual.ExtendedProperties.Count.ShouldBe(1); actual.ExtendedProperties.Single().ShouldBe(new KeyValuePair <string, object>("MyNumber", 42L)); actual.StackTrace.ShouldBe(expected.StackTrace); }
public ServiceProxyProvider(string serviceName, IEventPublisher <ClientCallEvent> eventPublisher, ILog log, Func <string, ReachabilityCheck, IMultiEnvironmentServiceDiscovery> serviceDiscoveryFactory, Func <DiscoveryConfig> getConfig, JsonExceptionSerializer exceptionSerializer, CurrentApplicationInfo appInfo, Func <HttpClientConfiguration, HttpMessageHandler> messageHandlerFactory, IMicrodotTypePolicySerializationBinder serializationBinder) { JsonSettings.SerializationBinder = serializationBinder; EventPublisher = eventPublisher; Log = log; ServiceName = serviceName; GetDiscoveryConfig = getConfig; ExceptionSerializer = exceptionSerializer; AppInfo = appInfo; var metricsContext = Metric.Context(METRICS_CONTEXT_NAME).Context(ServiceName); _serializationTime = metricsContext.Timer("Serialization", Unit.Calls); _deserializationTime = metricsContext.Timer("Deserialization", Unit.Calls); _roundtripTime = metricsContext.Timer("Roundtrip", Unit.Calls); _successCounter = metricsContext.Counter("Success", Unit.Calls); _failureCounter = metricsContext.Counter("Failed", Unit.Calls); _hostFailureCounter = metricsContext.Counter("HostFailure", Unit.Calls); _applicationExceptionCounter = metricsContext.Counter("ApplicationException", Unit.Calls); _httpMessageHandlerFactory = messageHandlerFactory; ServiceDiscovery = serviceDiscoveryFactory(serviceName, ValidateReachability); var globalConfig = GetDiscoveryConfig(); var serviceConfig = GetConfig(); _httpsTestInterval = TimeSpan.FromMinutes(serviceConfig.TryHttpsIntervalInMinutes ?? globalConfig.TryHttpsIntervalInMinutes); _connectionContext = Metric.Context("Connections"); }
public void SetUp() { var unitTesting = new TestingKernel <ConsoleLog>(k => k.Rebind <Func <StackTraceEnhancerSettings> >().ToConstant <Func <StackTraceEnhancerSettings> >(() => new StackTraceEnhancerSettings { RegexReplacements = { ["TidyAsyncMethodNames"] = new RegexReplace { Pattern = @"\.<(\w+)>d__\d+(?:`\d)?.MoveNext\(\)", Replacement = @".$1(async)" }, ["TidyAsyncLocalFunctionNames"] = new RegexReplace { Pattern = @"\.<>c__DisplayClass(?:\d+)_(?:\d+)(?:`\d)?\.<<(\w+)>g__(\w+)\d>d.MoveNext\(\)", Replacement = @".$1.$2(async)" }, ["RemoveBuildServerPath"] = new RegexReplace { Pattern = @"C:\\BuildAgent\\work\\\w+\\", Replacement = @"\" } } }) ); ExceptionSerializer = unitTesting.Get <JsonExceptionSerializer>(); }
private async Task <object> InvokeCore(HttpServiceRequest request, Type resultReturnType, JsonSerializerSettings jsonSettings) { if (request == null) { throw new ArgumentNullException(nameof(request)); } request.Overrides = TracingContext.TryGetOverrides(); request.TracingData = new TracingData { HostName = CurrentApplicationInfo.HostName?.ToUpperInvariant(), ServiceName = CurrentApplicationInfo.Name, RequestID = TracingContext.TryGetRequestID(), SpanID = Guid.NewGuid().ToString("N"), //Each call is new span ParentSpanID = TracingContext.TryGetSpanID() }; PrepareRequest?.Invoke(request); var requestContent = _serializationTime.Time(() => JsonConvert.SerializeObject(request, jsonSettings)); var serviceEvent = EventPublisher.CreateEvent(); serviceEvent.TargetService = ServiceName; serviceEvent.TargetMethod = request.Target.MethodName; serviceEvent.RequestId = request.TracingData?.RequestID; serviceEvent.SpanId = request.TracingData?.SpanID; serviceEvent.ParentSpanId = request.TracingData?.ParentSpanID; var config = GetConfig(); while (true) { string responseContent; HttpResponseMessage response; IEndPointHandle endPoint = await ServiceDiscovery.GetNextHost(serviceEvent.RequestId).ConfigureAwait(false); // The URL is only for a nice experience in Fiddler, it's never parsed/used for anything. var uri = string.Format(BuildUri(endPoint, config) + ServiceName); if (request.Target.MethodName != null) { uri += $".{request.Target.MethodName}"; } if (request.Target.Endpoint != null) { uri += $"/{request.Target.Endpoint}"; } try { Log.Debug(_ => _("ServiceProxy: Calling remote service. See tags for details.", unencryptedTags: new { remoteEndpoint = endPoint.HostName, remotePort = endPoint.Port ?? DefaultPort, remoteServiceName = ServiceName, remoteMethodName = request.Target.MethodName })); serviceEvent.TargetHostName = endPoint.HostName; var httpContent = new StringContent(requestContent, Encoding.UTF8, "application/json"); httpContent.Headers.Add(GigyaHttpHeaders.Version, HttpServiceRequest.Version); serviceEvent.RequestStartTimestamp = Stopwatch.GetTimestamp(); try { response = await GetHttpClient(config).PostAsync(uri, httpContent).ConfigureAwait(false); responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); } finally { serviceEvent.ResponseEndTimestamp = Stopwatch.GetTimestamp(); } IEnumerable <string> values; if (response.Headers.TryGetValues(GigyaHttpHeaders.ExecutionTime, out values)) { var time = values.FirstOrDefault(); TimeSpan executionTime; if (TimeSpan.TryParse(time, out executionTime)) { serviceEvent.ServerTimeMs = executionTime.TotalMilliseconds; } } } catch (HttpRequestException ex) { Log.Error("The remote service failed to return a valid HTTP response. Continuing to next " + "host. See tags for URL and exception for details.", exception: ex, unencryptedTags: new { uri }); endPoint.ReportFailure(ex); _hostFailureCounter.Increment("RequestFailure"); serviceEvent.Exception = ex; EventPublisher.TryPublish(serviceEvent); // fire and forget! continue; } catch (TaskCanceledException ex) { _failureCounter.Increment("RequestTimeout"); Exception rex = new RemoteServiceException("The request to the remote service exceeded the " + "allotted timeout. See the 'RequestUri' property on this exception for the URL that was " + "called and the tag 'requestTimeout' for the configured timeout.", uri, ex, unencrypted: new Tags { { "requestTimeout", LastHttpClient?.Timeout.ToString() }, { "requestUri", uri } }); serviceEvent.Exception = rex; EventPublisher.TryPublish(serviceEvent); // fire and forget! throw rex; } if (response.Headers.Contains(GigyaHttpHeaders.ServerHostname) || response.Headers.Contains(GigyaHttpHeaders.Version)) { try { endPoint.ReportSuccess(); if (response.IsSuccessStatusCode) { var returnObj = _deserializationTime.Time(() => JsonConvert.DeserializeObject(responseContent, resultReturnType, jsonSettings)); serviceEvent.ErrCode = 0; EventPublisher.TryPublish(serviceEvent); // fire and forget! _successCounter.Increment(); return(returnObj); } else { Exception remoteException; try { remoteException = _deserializationTime.Time(() => JsonExceptionSerializer.Deserialize(responseContent)); } catch (Exception ex) { _applicationExceptionCounter.Increment("ExceptionDeserializationFailure"); throw new RemoteServiceException("The remote service returned a failure response " + "that failed to deserialize. See the 'RequestUri' property on this exception " + "for the URL that was called, the inner exception for the exact error and the " + "'responseContent' encrypted tag for the original response content.", uri, ex, unencrypted: new Tags { { "requestUri", uri } }, encrypted: new Tags { { "responseContent", responseContent } }); } _applicationExceptionCounter.Increment(); serviceEvent.Exception = remoteException; EventPublisher.TryPublish(serviceEvent); // fire and forget! if (remoteException is RequestException || remoteException is EnvironmentException) { ExceptionDispatchInfo.Capture(remoteException).Throw(); } if (remoteException is UnhandledException) { remoteException = remoteException.InnerException; } throw new RemoteServiceException("The remote service returned a failure response. See " + "the 'RequestUri' property on this exception for the URL that was called, and the " + "inner exception for details.", uri, remoteException, unencrypted: new Tags { { "requestUri", uri } }); } } catch (JsonException ex) { _failureCounter.Increment("Serialization"); Log.Error(_ => _("The remote service returned a response with JSON that failed " + "deserialization. See the 'uri' tag for the URL that was called, the exception for the " + "exact error and the 'responseContent' encrypted tag for the original response content.", exception: ex, unencryptedTags: new { uri }, encryptedTags: new { responseContent })); serviceEvent.Exception = ex; EventPublisher.TryPublish(serviceEvent); // fire and forget! throw new RemoteServiceException("The remote service returned a response with JSON that " + "failed deserialization. See the 'RequestUri' property on this exception for the URL " + "that was called, the inner exception for the exact error and the 'responseContent' " + "encrypted tag for the original response content.", uri, ex, new Tags { { "responseContent", responseContent } }, new Tags { { "requestUri", uri } }); } } else { var exception = response.StatusCode == HttpStatusCode.ServiceUnavailable ? new Exception($"The remote service is unavailable (503) and is not recognized as a Gigya host at uri: {uri}"): new Exception($"The remote service returned a response but is not recognized as a Gigya host at uri: {uri}"); endPoint.ReportFailure(exception); _hostFailureCounter.Increment("NotGigyaHost"); if (response.StatusCode == HttpStatusCode.ServiceUnavailable) { Log.Error(_ => _("The remote service is unavailable (503) and is not recognized as a Gigya host. Continuing to next host.", unencryptedTags: new { uri })); } else { Log.Error(_ => _("The remote service returned a response but is not recognized as a Gigya host. Continuing to next host.", unencryptedTags: new { uri, statusCode = response.StatusCode }, encryptedTags: new { responseContent })); } serviceEvent.ErrCode = 500001; //(int)GSErrors.General_Server_Error; EventPublisher.TryPublish(serviceEvent); // fire and forget! } } }
public JsonExceptionWrapperTest() { Subject = new JsonExceptionSerializer(); }
private async Task HandleRequest(HttpListenerContext context) { RequestTimings.ClearCurrentTimings(); using (context.Response) { var sw = Stopwatch.StartNew(); // Special endpoints should not be logged/measured/traced like regular endpoints try { foreach (var customEndpoint in CustomEndpoints) { if (await customEndpoint.TryHandle(context, (data, status, type) => TryWriteResponse(context, data, status, type))) { if (RequestTimings.Current.Request.ElapsedMS != null) { _metaEndpointsRoundtripTime.Record((long)RequestTimings.Current.Request.ElapsedMS, TimeUnit.Milliseconds); } return; } } } catch (Exception e) { var ex = GetRelevantException(e); await TryWriteResponse(context, JsonExceptionSerializer.Serialize(ex), GetExceptionStatusCode(ex)); return; } // Regular endpoint handling using (_activeRequestsCounter.NewContext("Request")) { TracingContext.SetUpStorage(); Exception ex; Exception actualException = null; string methodName = null; // Initialize with empty object for protocol backwards-compatibility. var requestData = new HttpServiceRequest { TracingData = new TracingData() }; ServiceMethod serviceMethod = null; try { try { ValidateRequest(context); await CheckSecureConnection(context); requestData = await ParseRequest(context); TracingContext.SetOverrides(requestData.Overrides); serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target); methodName = serviceMethod.ServiceInterfaceMethod.Name; } catch (Exception e) { actualException = e; if (e is RequestException) { throw; } throw new RequestException("Invalid request", e); } var responseJson = await GetResponse(context, serviceMethod, requestData); await TryWriteResponse(context, responseJson); _successCounter.Increment(); } catch (Exception e) { actualException = actualException ?? e; _failureCounter.Increment(); ex = GetRelevantException(e); string json = _serializationTime.Time(() => JsonExceptionSerializer.Serialize(ex)); await TryWriteResponse(context, json, GetExceptionStatusCode(ex)); } finally { sw.Stop(); _roundtripTime.Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds); if (methodName != null) { _endpointContext.Timer(methodName, Unit.Requests).Record((long)(sw.Elapsed.TotalMilliseconds * 1000000), TimeUnit.Nanoseconds); } PublishEvent(requestData, actualException, serviceMethod, sw.Elapsed.TotalMilliseconds); } } } }
public HttpServiceListener( IActivator activator, IWorker worker, IServiceEndPointDefinition serviceEndPointDefinition, ICertificateLocator certificateLocator, ILog log, IEnumerable <ICustomEndpoint> customEndpoints, IEnvironment environment, JsonExceptionSerializer exceptionSerializer, ServiceSchema serviceSchema, Func <LoadShedding> loadSheddingConfig, IServerRequestPublisher serverRequestPublisher, CurrentApplicationInfo appInfo, Func <MicrodotHostingConfig> microdotHostingConfigFactory, IMicrodotTypePolicySerializationBinder serializationBinder) { ServiceSchema = serviceSchema; _serverRequestPublisher = serverRequestPublisher; ServiceEndPointDefinition = serviceEndPointDefinition; Worker = worker; Activator = activator; Log = log; CustomEndpoints = customEndpoints.ToArray(); Environment = environment; ExceptionSerializer = exceptionSerializer; LoadSheddingConfig = loadSheddingConfig; AppInfo = appInfo; JsonSettings.SerializationBinder = serializationBinder; if (ServiceEndPointDefinition.HttpsPort != null && ServiceEndPointDefinition.ClientCertificateVerification != ClientCertificateVerificationMode.Disable) { var serviceCertificate = certificateLocator.GetCertificate("Service"); Log.Info(_ => _($"Service certificate loaded: {serviceCertificate.FriendlyName}", unencryptedTags: new { Thumbprint = serviceCertificate.Thumbprint.Substring(serviceCertificate.Thumbprint.Length - 5), })); ServerRootCertHash = serviceCertificate.GetHashOfRootCertificate(); } Listener = new HttpListener { IgnoreWriteExceptions = true }; _uriPrefixes = new List <string>(); if (ServiceEndPointDefinition.HttpsPort != null) { _uriPrefixes.Add($"https://+:{ServiceEndPointDefinition.HttpsPort}/"); } if (ServiceEndPointDefinition.HttpPort != null) { _uriPrefixes.Add($"http://+:{ServiceEndPointDefinition.HttpPort}/"); } if (!_uriPrefixes.Any()) { Log.Warn(_ => _("HttpServiceListener is not listening on any ports, no HTTP or HTTPS ports in ServiceEndPointDefinition")); } else { foreach (string prefix in _uriPrefixes) { Listener.Prefixes.Add(prefix); } } var context = Metric.Context("Service").Context(AppInfo.Name); _serializationTime = context.Timer("Serialization", Unit.Calls); _deserializationTime = context.Timer("Deserialization", Unit.Calls); _roundtripTime = context.Timer("Roundtrip", Unit.Calls); _metaEndpointsRoundtripTime = context.Timer("MetaRoundtrip", Unit.Calls); _successCounter = context.Counter("Success", Unit.Calls); _failureCounter = context.Counter("Failed", Unit.Calls); _activeRequestsCounter = context.Timer("ActiveRequests", Unit.Requests); _endpointContext = context.Context("Endpoints"); }