private static object[] GetParametersByName(ServiceMethod serviceMethod, IDictionary args) { return(serviceMethod.ServiceInterfaceMethod .GetParameters() .Select(p => JsonHelper.ConvertWeaklyTypedValue(args[p.Name], p.ParameterType)) .ToArray()); }
private async Task <string> GetResponse(HttpListenerContext context, ServiceMethod serviceMethod, HttpServiceRequest requestData) { var taskType = serviceMethod.ServiceInterfaceMethod.ReturnType; var resultType = taskType.IsGenericType ? taskType.GetGenericArguments().First() : null; string response; InvocationResult invocationResult; if (requestData.Target.IsWeaklyTyped) { invocationResult = await Activator.Invoke(serviceMethod, requestData.Arguments); response = _serializationTime.Time(() => JsonConvert.SerializeObject(invocationResult.Result, resultType, JsonSettingsWeak)); } else { invocationResult = await Activator.Invoke(serviceMethod, requestData.Arguments.Values.Cast <object>().ToArray()); response = _serializationTime.Time(() => JsonConvert.SerializeObject(invocationResult.Result, resultType, JsonSettings)); } context.Response.Headers.Add(GigyaHttpHeaders.ExecutionTime, invocationResult.ExecutionTime.ToString()); return(response); }
public void TryPublish(HttpServiceRequest requestData, Exception ex, ServiceMethod serviceMethod, double requestTime) { var callEvent = _eventPublisher.CreateEvent(); callEvent.CalledServiceName = serviceMethod?.GrainInterfaceType.Name; callEvent.ClientMetadata = requestData.TracingData; callEvent.ServiceMethod = requestData.Target?.MethodName; var metaData = _serviceEndPointDefinition.GetMetaData(serviceMethod); var arguments = (requestData.Arguments ?? new OrderedDictionary()).Cast <DictionaryEntry>(); var @params = new List <Param>(); foreach (var argument in arguments) { foreach (var(name, value, sensitivity) in ExtractParamValues(argument, metaData)) { @params.Add(new Param { Name = name, Value = value is string?value.ToString() : JsonConvert.SerializeObject(value), Sensitivity = sensitivity }); } } callEvent.Params = @params; callEvent.Exception = ex; callEvent.ActualTotalTime = requestTime; callEvent.ErrCode = ex != null ? null : (int?)0; _eventPublisher.TryPublish(callEvent); }
private static object[] GetParametersByName(ServiceMethod serviceMethod, IDictionary args) { return(serviceMethod.ServiceInterfaceMethod .GetParameters() .Select(p => args[p.Name] ?? (p.ParameterType.IsValueType ? System.Activator.CreateInstance(p.ParameterType) : null)) .ToArray()); }
public EndPointMetadata(ServiceMethod method) { MethodSensitivity = GetSensitivity(method.ServiceInterfaceMethod); var parametersSensitivity = ImmutableDictionary.CreateBuilder<string, Sensitivity?>(); foreach (var pram in method.ServiceInterfaceMethod.GetParameters()) { parametersSensitivity.Add(pram.Name, GetSensitivity(pram)); } ParametersSensitivity = parametersSensitivity.ToImmutable(); }
private async Task <string> GetResponse(HttpListenerContext context, ServiceMethod serviceMethod, HttpServiceRequest requestData, object[] arguments) { var taskType = serviceMethod.ServiceInterfaceMethod.ReturnType; var resultType = taskType.IsGenericType ? taskType.GetGenericArguments().First() : null; var settings = requestData.Target.IsWeaklyTyped ? JsonSettingsWeak : JsonSettings; var invocationResult = await Activator.Invoke(serviceMethod, arguments); string response = _serializationTime.Time(() => JsonConvert.SerializeObject(invocationResult.Result, resultType, settings)); context.Response.Headers.Add(GigyaHttpHeaders.ExecutionTime, invocationResult.ExecutionTime.ToString()); return(response); }
public async Task <InvocationResult> Invoke(ServiceMethod serviceMethod, object[] argumentsWithDefaults) { var invokeTarget = GetInvokeTarget(serviceMethod); var sw = Stopwatch.StartNew(); var task = (Task)serviceMethod.ServiceInterfaceMethod.Invoke(invokeTarget, argumentsWithDefaults); await task.ConfigureAwait(false); var executionTime = sw.Elapsed; var result = task.GetType().GetProperty("Result").GetValue(task); return(new InvocationResult { Result = result, ExecutionTime = executionTime }); }
public void TryPublish(ServiceCallEvent callEvent, object[] arguments, ServiceMethod serviceMethod) { try { if (arguments != null) { callEvent.Params = ExtractParamValues(arguments, serviceMethod); } } catch (Exception e) { _log.Error("Can not extract params from request", exception: e, unencryptedTags: new { serviceInterfaceMethod = serviceMethod.ServiceInterfaceMethod.Name }); } _eventPublisher.TryPublish(callEvent); }
private void PublishEvent(HttpServiceRequest requestData, Exception ex, ServiceMethod serviceMethod, double requestTime) { var callEvent = EventPublisher.CreateEvent(); callEvent.CalledServiceName = serviceMethod?.GrainInterfaceType.Name; callEvent.ClientMetadata = requestData.TracingData; callEvent.ServiceMethod = requestData.Target?.MethodName; callEvent.Params = (requestData.Arguments ?? new OrderedDictionary()).Cast <DictionaryEntry>().Select(arg => new Param { Name = arg.Key.ToString(), Value = arg.Value is string?arg.Value.ToString() : JsonConvert.SerializeObject(arg.Value) }); callEvent.Exception = ex; callEvent.ActualTotalTime = requestTime; callEvent.ErrCode = ex != null ? null : (int?)0; EventPublisher.TryPublish(callEvent); // fire and forget! }
private static object[] GetParametersByName(ServiceMethod serviceMethod, IDictionary args) { return(serviceMethod.ServiceInterfaceMethod .GetParameters() .Select(p => { try { return JsonHelper.ConvertWeaklyTypedValue(args[p.Name], p.ParameterType); } catch (InvalidParameterValueException ex) { if (ex.parameterName != null) { throw; } throw new InvalidParameterValueException(p.Name, ex.ErrorPath, ex.Message, ex); } }). ToArray()); }
public void TryPublish(HttpServiceRequest requestData, Exception ex, ServiceMethod serviceMethod, double requestTime) { var callEvent = _eventPublisher.CreateEvent(); callEvent.CalledServiceName = serviceMethod?.GrainInterfaceType.Name; callEvent.ClientMetadata = requestData.TracingData; callEvent.ServiceMethod = requestData.Target?.MethodName; var metaData = _serviceEndPointDefinition.GetMetaData(serviceMethod); var arguments = (requestData.Arguments ?? new OrderedDictionary()).Cast <DictionaryEntry>(); callEvent.Params = arguments.SelectMany(_ => ExtractParamValues(_, metaData)).Select(_ => new Param { Name = _.name, Value = _.value, Sensitivity = _.sensitivity, }); callEvent.Exception = ex; callEvent.ActualTotalTime = requestTime; callEvent.ErrCode = ex != null ? null : (int?)0; _eventPublisher.TryPublish(callEvent); }
private IEnumerable <Param> ExtractParamValues(object[] arguments, ServiceMethod serviceMethod) { EndPointMetadata metaData = _serviceEndPointDefinition.GetMetaData(serviceMethod); var methodParameterInfos = serviceMethod.ServiceInterfaceMethod.GetParameters(); for (int i = 0; i < arguments.Length; i++) { var parameterInfo = methodParameterInfos[i]; var value = arguments[i]; var sensitivity = metaData.ParameterAttributes[parameterInfo.Name].Sensitivity ?? metaData.MethodSensitivity ?? Sensitivity.Sensitive; if (metaData.ParameterAttributes[parameterInfo.Name].IsLogFieldAttributeExists == true && (value is string) == false && value?.GetType().IsClass == true) { var metaParams = _membersToLogExtractor.ExtractMembersToLog(value); foreach (var metaParam in metaParams) { yield return(new Param { Name = string.Intern($"{parameterInfo.Name}_{metaParam.Name}"), Value = metaParam.Value, Sensitivity = metaParam.Sensitivity ?? sensitivity }); } } else { yield return(new Param { Name = parameterInfo.Name, Value = value, Sensitivity = sensitivity }); } } ; }
public void TryPublish(ServiceCallEvent callEvent, IEnumerable <DictionaryEntry> arguments, ServiceMethod serviceMethod) { EndPointMetadata metaData = _serviceEndPointDefinition.GetMetaData(serviceMethod); callEvent.Params = arguments.SelectMany(_ => ExtractParamValues(_, metaData)).Select(_ => new Param { Name = _.name, Value = _.value, Sensitivity = _.sensitivity, }); _eventPublisher.TryPublish(callEvent); }
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, ExceptionSerializer.Serialize(ex), GetExceptionStatusCode(ex)); return; } // Regular endpoint handling using (_activeRequestsCounter.NewContext("Request")) { TracingContext.SetUpStorage(); RequestTimings.GetOrCreate(); // initialize request timing context 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(() => ExceptionSerializer.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 EndPointMetadata(ServiceMethod method) { Initialize(method); }
public EndPointMetadata GetMetaData(ServiceMethod method) { return(_metadata.GetOrAdd(method, m => new EndPointMetadata(m))); }
private async Task HandleRequest(HttpListenerContext context, long ticks, long timeFromLastReq) { try { var deltaDelayTicks = DateTime.UtcNow.Ticks - ticks; var sw = Stopwatch.StartNew(); RequestTimings.ClearCurrentTimings(); using (context.Response) { // Special endpoints should not be logged/measured/traced like regular endpoints // Access is allowed without HTTPS verifications since they don't expose anything sensitive (e.g. config values are encrypted) if (await TryHandleSpecialEndpoints(context)) { return; } // Regular endpoint handling using (_activeRequestsCounter.NewContext("Request")) { RequestTimings.GetOrCreate(); // initialize request timing context string methodName = null; // Initialize with empty object for protocol backwards-compatibility. var requestData = new HttpServiceRequest { TracingData = new TracingData() }; object[] argumentsWithDefaults = null; ServiceMethod serviceMethod = null; ServiceCallEvent callEvent = _serverRequestPublisher.GetNewCallEvent(); try { try { await CheckSecureConnection(context); ValidateRequest(context); requestData = await ParseRequest(context); //----------------------------------------------------------------------------------------- // Don't move TracingContext writes main flow, IT have to be here, to avoid side changes //----------------------------------------------------------------------------------------- TracingContext.SetRequestID(requestData.TracingData.RequestID); TracingContext.SpanStartTime = requestData.TracingData.SpanStartTime; TracingContext.AbandonRequestBy = requestData.TracingData.AbandonRequestBy; TracingContext.SetParentSpan( requestData.TracingData.SpanID ?? Guid.NewGuid().ToString("N")); TracingContext.SetOverrides(requestData.Overrides); if (requestData.TracingData.Tags != null) { TracingContext.Tags = new ContextTags(requestData.TracingData.Tags); } TracingContext.AdditionalProperties = requestData.TracingData.AdditionalProperties; callEvent.ServiceMethodSchema = context.Request.IsSecureConnection ? "HTTPS" : "HTTP"; SetCallEventRequestData(callEvent, requestData); serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target); callEvent.CalledServiceName = serviceMethod.GrainInterfaceType.Name; methodName = serviceMethod.ServiceInterfaceMethod.Name; var arguments = requestData.Target.IsWeaklyTyped ? GetParametersByName(serviceMethod, requestData.Arguments) : requestData.Arguments.Values.Cast <object>().ToArray(); argumentsWithDefaults = GetConvertedAndDefaultArguments(serviceMethod.ServiceInterfaceMethod, arguments); if (_extendedDelayTimeLogging) { callEvent.RecvDateTicks = ticks; callEvent.ReqStartupDeltaTicks = deltaDelayTicks; callEvent.TimeFromLastReq = timeFromLastReq; var outstandingReqs = Interlocked.Read(ref OutstandingRequests); callEvent.OutstandingRequests = outstandingReqs; if (deltaDelayTicks > 10_000_000) { callEvent.CollectionCountGen0 = GC.CollectionCount(0); callEvent.CollectionCountGen1 = GC.CollectionCount(1); callEvent.CollectionCountGen2 = GC.CollectionCount(2); } } } catch (Exception e) { callEvent.Exception = e; if (e is RequestException) { throw; } throw new RequestException("Invalid request", e); } RejectRequestIfLateOrOverloaded(); var responseJson = await GetResponse(context, serviceMethod, requestData, argumentsWithDefaults); if (await TryWriteResponse(context, responseJson, serviceCallEvent: callEvent)) { callEvent.ErrCode = 0; _successCounter.Increment(); } else { _failureCounter.Increment(); } } catch (Exception e) { callEvent.Exception = callEvent.Exception ?? e; _failureCounter.Increment(); Exception ex = GetRelevantException(e); string json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex)); await TryWriteResponse(context, json, GetExceptionStatusCode(ex), serviceCallEvent : callEvent); } finally { sw.Stop(); callEvent.ActualTotalTime = sw.Elapsed.TotalMilliseconds; _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); } _serverRequestPublisher.TryPublish(callEvent, argumentsWithDefaults, serviceMethod); } } } } finally { Interlocked.Decrement(ref OutstandingRequests); } }
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 if (await TryHandleSpecialEndpoints(context)) { return; } // Regular endpoint handling using (_activeRequestsCounter.NewContext("Request")) { TracingContext.SetUpStorage(); RequestTimings.GetOrCreate(); // initialize request timing context string methodName = null; // Initialize with empty object for protocol backwards-compatibility. var requestData = new HttpServiceRequest { TracingData = new TracingData() }; ServiceMethod serviceMethod = null; ServiceCallEvent callEvent = _serverRequestPublisher.GetNewCallEvent(); try { try { ValidateRequest(context); await CheckSecureConnection(context); requestData = await ParseRequest(context); SetCallEventRequestData(callEvent, requestData); TracingContext.SetOverrides(requestData.Overrides); serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target); callEvent.CalledServiceName = serviceMethod.GrainInterfaceType.Name; methodName = serviceMethod.ServiceInterfaceMethod.Name; } catch (Exception e) { callEvent.Exception = e; if (e is RequestException) { throw; } throw new RequestException("Invalid request", e); } RejectRequestIfLateOrOverloaded(); var responseJson = await GetResponse(context, serviceMethod, requestData); if (await TryWriteResponse(context, responseJson, serviceCallEvent: callEvent)) { callEvent.ErrCode = 0; _successCounter.Increment(); } else { _failureCounter.Increment(); } } catch (Exception e) { callEvent.Exception = callEvent.Exception ?? e; _failureCounter.Increment(); Exception ex = GetRelevantException(e); string json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex)); await TryWriteResponse(context, json, GetExceptionStatusCode(ex), serviceCallEvent : callEvent); } finally { sw.Stop(); callEvent.ActualTotalTime = sw.Elapsed.TotalMilliseconds; _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); } IEnumerable <DictionaryEntry> arguments = (requestData.Arguments ?? new OrderedDictionary()).Cast <DictionaryEntry>(); _serverRequestPublisher.TryPublish(callEvent, arguments, serviceMethod); } } } }
public async Task <InvocationResult> Invoke(ServiceMethod serviceMethod, IDictionary args) { var arguments = GetParametersByName(serviceMethod, args); return(await Invoke(serviceMethod, arguments).ConfigureAwait(false)); }
protected abstract object GetInvokeTarget(ServiceMethod serviceMethod);
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 if (await TryHandleSpecialEndpoints(context)) { return; } // Regular endpoint handling using (_activeRequestsCounter.NewContext("Request")) { RequestTimings.GetOrCreate(); // initialize request timing context string methodName = null; // Initialize with empty object for protocol backwards-compatibility. var requestData = new HttpServiceRequest { TracingData = new TracingData() }; object[] argumentsWithDefaults = null; ServiceMethod serviceMethod = null; ServiceCallEvent callEvent = _serverRequestPublisher.GetNewCallEvent(); try { try { ValidateRequest(context); await CheckSecureConnection(context); requestData = await ParseRequest(context); //----------------------------------------------------------------------------------------- // Don't move TracingContext writes main flow, IT have to be here, to avoid side changes //----------------------------------------------------------------------------------------- TracingContext.SetRequestID(requestData.TracingData.RequestID); TracingContext.SpanStartTime = requestData.TracingData.SpanStartTime; TracingContext.AbandonRequestBy = requestData.TracingData.AbandonRequestBy; TracingContext.SetParentSpan(requestData.TracingData.SpanID ?? Guid.NewGuid().ToString("N")); SetCallEventRequestData(callEvent, requestData); TracingContext.SetOverrides(requestData.Overrides); serviceMethod = ServiceEndPointDefinition.Resolve(requestData.Target); callEvent.CalledServiceName = serviceMethod.GrainInterfaceType.Name; methodName = serviceMethod.ServiceInterfaceMethod.Name; var arguments = requestData.Target.IsWeaklyTyped ? GetParametersByName(serviceMethod, requestData.Arguments) : requestData.Arguments.Values.Cast <object>().ToArray(); argumentsWithDefaults = GetConvertedAndDefaultArguments(serviceMethod.ServiceInterfaceMethod, arguments); } catch (Exception e) { callEvent.Exception = e; if (e is RequestException) { throw; } throw new RequestException("Invalid request", e); } RejectRequestIfLateOrOverloaded(); var responseJson = await GetResponse(context, serviceMethod, requestData, argumentsWithDefaults); if (await TryWriteResponse(context, responseJson, serviceCallEvent: callEvent)) { callEvent.ErrCode = 0; _successCounter.Increment(); } else { _failureCounter.Increment(); } } catch (Exception e) { callEvent.Exception = callEvent.Exception ?? e; _failureCounter.Increment(); Exception ex = GetRelevantException(e); string json = _serializationTime.Time(() => ExceptionSerializer.Serialize(ex)); await TryWriteResponse(context, json, GetExceptionStatusCode(ex), serviceCallEvent : callEvent); } finally { sw.Stop(); callEvent.ActualTotalTime = sw.Elapsed.TotalMilliseconds; _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); } _serverRequestPublisher.TryPublish(callEvent, argumentsWithDefaults, serviceMethod); } } } }