private bool IsSpecified(JsonWriter writer, JsonProperty property, object target) { if (property.GetIsSpecified == null) { return(true); } bool isSpecified = property.GetIsSpecified(target); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "IsSpecified result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, isSpecified)), null); } return(isSpecified); }
private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target) { if (property.ShouldSerialize == null) { return(true); } bool shouldSerialize = property.ShouldSerialize(target); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "ShouldSerialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, shouldSerialize)), null); } return(shouldSerialize); }
/// <summary> /// Emit the provided log event to an Azure WebJobs <see cref="TraceWriter"/>. /// </summary> /// <param name="logEvent">The log event to write.</param> public void Emit(LogEvent logEvent) { if (logEvent == null) { throw new ArgumentNullException(nameof(logEvent)); } lock (_lock) { TraceLevel traceLevel = GetTraceLevel(logEvent.Level); string message = logEvent.RenderMessage(_formatProvider); Exception exception = logEvent.Exception; var traceEvent = new TraceEvent(traceLevel, message, SourceName, exception); _trace.Trace(traceEvent); } }
public void Log <TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter) { IEnumerable <KeyValuePair <string, object> > properties = state as IEnumerable <KeyValuePair <string, object> >; string formattedMessage = formatter?.Invoke(state, exception); // If we have no structured data and no message, there's nothing to log if ((string.IsNullOrEmpty(formattedMessage) && properties == null) || !IsEnabled(logLevel)) { return; } TraceEvent traceEvent = new TraceEvent(logLevel.ToTraceLevel(), formattedMessage, _categoryName, exception); TraceWriter traceWriter = _traceWriterFactory.Create(_language, "Worker"); traceWriter.Trace(traceEvent); }
public void Initialize(ExtensionConfigContext context) { if (context == null) { throw new ArgumentNullException("context"); } else if (context.Trace == null) { throw new ArgumentNullException("context.Trace"); } _tracer = context.Trace; Uri url = context.GetWebhookHandler(); _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"registered EventGrid Endpoint = {url}")); // Register our extension binding providers context.Config.RegisterBindingExtension(new EventGridTriggerAttributeBindingProvider(this)); }
public static void Trace(this TraceWriter traceWriter, string message, TraceLevel level, IDictionary <string, object> properties) { TraceEvent traceEvent = CreateEvent(message, level, properties); traceWriter.Trace(traceEvent); }
protected void TraceOnPrimaryHost(string message, TraceLevel level) { TraceWriter.Trace(message, level, PrimaryHostTraceProperties); }
private async Task <HttpResponseMessage> ProcessAsync(HttpRequestMessage req) { // webjobs.script uses req.GetQueryNameValuePairs(); // which requires webapi.core...but this does not work for .netframework2.0 // TODO change this once webjobs.script is migrated var functionName = HttpUtility.ParseQueryString(req.RequestUri.Query)["functionName"]; if (String.IsNullOrEmpty(functionName) || !_listeners.ContainsKey(functionName)) { _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"cannot find function: '{functionName}', available function names: [{string.Join(", ", _listeners.Keys.ToArray())}]")); return(new HttpResponseMessage(HttpStatusCode.NotFound)); } IEnumerable <string> eventTypeHeaders = null; string eventTypeHeader = null; if (req.Headers.TryGetValues("aeg-event-type", out eventTypeHeaders)) { eventTypeHeader = eventTypeHeaders.First(); } if (String.Equals(eventTypeHeader, "SubscriptionValidation", StringComparison.OrdinalIgnoreCase)) { string jsonArray = await req.Content.ReadAsStringAsync(); SubscriptionValidationEvent validationEvent = null; List <JObject> events = JsonConvert.DeserializeObject <List <JObject> >(jsonArray); // TODO remove unnecessary serialization validationEvent = ((JObject)events[0]["data"]).ToObject <SubscriptionValidationEvent>(); SubscriptionValidationResponse validationResponse = new SubscriptionValidationResponse { ValidationResponse = validationEvent.ValidationCode }; var returnMessage = new HttpResponseMessage(HttpStatusCode.OK); returnMessage.Content = new StringContent(JsonConvert.SerializeObject(validationResponse)); _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"perform handshake with eventGrid for endpoint: {req.RequestUri}")); return(returnMessage); } else if (String.Equals(eventTypeHeader, "Notification", StringComparison.OrdinalIgnoreCase)) { string jsonArray = await req.Content.ReadAsStringAsync(); List <JObject> events = JsonConvert.DeserializeObject <List <JObject> >(jsonArray); foreach (var ev in events) { TriggeredFunctionData triggerData = new TriggeredFunctionData { TriggerValue = ev }; await _listeners[functionName].Executor.TryExecuteAsync(triggerData, CancellationToken.None); } return(new HttpResponseMessage(HttpStatusCode.Accepted)); } else if (String.Equals(eventTypeHeader, "Unsubscribe", StringComparison.OrdinalIgnoreCase)) { // TODO disable function? return(new HttpResponseMessage(HttpStatusCode.Accepted)); } return(new HttpResponseMessage(HttpStatusCode.BadRequest)); }
internal virtual object DeserializeInternal(JsonReader reader, Type objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); // set serialization options onto reader CultureInfo previousCulture = null; if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } DateTimeZoneHandling?previousDateTimeZoneHandling = null; if (_dateTimeZoneHandling != null && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = reader.DateTimeZoneHandling; reader.DateTimeZoneHandling = _dateTimeZoneHandling.Value; } DateParseHandling?previousDateParseHandling = null; if (_dateParseHandling != null && reader.DateParseHandling != _dateParseHandling) { previousDateParseHandling = reader.DateParseHandling; reader.DateParseHandling = _dateParseHandling.Value; } FloatParseHandling?previousFloatParseHandling = null; if (_floatParseHandling != null && reader.FloatParseHandling != _floatParseHandling) { previousFloatParseHandling = reader.FloatParseHandling; reader.FloatParseHandling = _floatParseHandling.Value; } int?previousMaxDepth = null; if (_maxDepthSet && reader.MaxDepth != _maxDepth) { previousMaxDepth = reader.MaxDepth; reader.MaxDepth = _maxDepth; } TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonReader(reader) : null; JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this); object value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, "Deserialized JSON: " + Environment.NewLine + traceJsonReader.GetJson(), null); } // reset reader back to previous options if (previousCulture != null) { reader.Culture = previousCulture; } if (previousDateTimeZoneHandling != null) { reader.DateTimeZoneHandling = previousDateTimeZoneHandling.Value; } if (previousDateParseHandling != null) { reader.DateParseHandling = previousDateParseHandling.Value; } if (previousFloatParseHandling != null) { reader.FloatParseHandling = previousFloatParseHandling.Value; } if (_maxDepthSet) { reader.MaxDepth = previousMaxDepth; } return(value); }
public static async Task <HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { var url = string.Empty; var stopwatch = Stopwatch.StartNew(); var jsonResponse = string.Empty; try { var reqBodyStr = await req.Content.ReadAsStringAsync(); var reqBody = JsonConvert.DeserializeObject <URLHolder>(reqBodyStr); url = reqBody.Url; if (!string.IsNullOrEmpty(reqBody.Parameter)) { url += reqBody.Parameter; } log.Info("RSS " + url); // TODO: use HttpCachedService (also as means of failover if the RSS stream is down) string data = await client.GetStringAsync(reqBody.Url.ToString()); var rss = XDocument.Parse(data); string parseFormat = "ddd, dd MMM yyyy HH:mm:ss zzz"; string parseFormat2 = "ddd, dd MMM yyyy HH:mm:ss Z"; var items = rss.DescendantNodes() .OfType <XElement>() .Where(a => a.Name == "item") .Select((elem, index) => { var pubDateStr = elem.Descendants("pubDate").FirstOrDefault()?.Value; if (pubDateStr != null) { pubDateStr = pubDateStr.Trim(); } DateTime pubDate; if (!DateTime.TryParseExact(pubDateStr, parseFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out pubDate)) { if (!DateTime.TryParseExact(pubDateStr, parseFormat2, CultureInfo.InvariantCulture, DateTimeStyles.None, out pubDate)) { pubDate = DateTime.UtcNow; } } return(new { elem, pubDate, index }); }) .OrderByDescending(elem => elem.pubDate) // limit the feed to avoid getting too many .Take(15) // Note: this is very important for the Dashboard // The order of the items allows customers to specify their base-line policy .OrderBy(elem => elem.index) .Select(x => x.elem); var actions = items.Select(x => new { ids = new[] { new { id = x.Descendants("link").FirstOrDefault()?.Value } }, features = new { _title = x.Descendants("title").FirstOrDefault()?.Value }, details = new [] { // TODO: properly support 4.2.6. The "atom:id" Element new { guid = x.Descendants("guid").FirstOrDefault()?.Value } } }).ToList(); jsonResponse = JsonConvert.SerializeObject(actions); if (log.Level == TraceLevel.Verbose) { log.Trace(new TraceEvent(TraceLevel.Verbose, $"Successfully transformed '{url}' '{data}' to '{jsonResponse}'")); } else { log.Info($"Successfully transformed '{url}'"); } } catch (HttpRequestException hre) { var msg = $"RSS Featurization failed '{url}' for '{req.RequestUri.ToString()}': '{hre.Message}'"; log.Warning(msg); // TODO: maybe switch to dependency w/ status failed? Services.TelemetryClient.TrackEvent(msg, new Dictionary <string, string> { { "Service", req.RequestUri.ToString() }, { "Url", url }, { "Exception", hre.Message } }); } catch (Exception ex) { log.Error($"Failed to process '{url}'", ex); Services.TelemetryClient.TrackException( ex, new Dictionary <string, string> { { "Service", req.RequestUri.ToString() }, { "Url", url } }); // swallow the error message and return empty. That way we can differentiate between real outages // remote errors } finally { Services.TelemetryClient.TrackEvent($"RSS {url}", metrics: new Dictionary <string, double> { { "requestTime", stopwatch.ElapsedMilliseconds } }); } return(new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StringContent( jsonResponse, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), "application/json") }); }
public void Log(TraceLevel level, string message, Exception ex) { // Route all logs coming from the WebHooks SDK to the WebJobs SDK // as Verbose. _traceWriter.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Verbose, message, null, ex)); }
private async Task <HttpResponseMessage> ProcessAsync(HttpRequestMessage req) { // webjobs.script uses req.GetQueryNameValuePairs(); // which requires webapi.core...but this does not work for .netframework2.0 // TODO change this once webjobs.script is migrated var functionName = HttpUtility.ParseQueryString(req.RequestUri.Query)["functionName"]; if (String.IsNullOrEmpty(functionName) || !_listeners.ContainsKey(functionName)) { _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"cannot find function: '{functionName}', available function names: [{string.Join(", ", _listeners.Keys.ToArray())}]")); return(new HttpResponseMessage(HttpStatusCode.NotFound) { Content = new StringContent($"cannot find function: '{functionName}'") }); } IEnumerable <string> eventTypeHeaders = null; string eventTypeHeader = null; if (req.Headers.TryGetValues("aeg-event-type", out eventTypeHeaders)) { eventTypeHeader = eventTypeHeaders.First(); } if (String.Equals(eventTypeHeader, "SubscriptionValidation", StringComparison.OrdinalIgnoreCase)) { string jsonArray = await req.Content.ReadAsStringAsync(); SubscriptionValidationEvent validationEvent = null; List <JObject> events = JsonConvert.DeserializeObject <List <JObject> >(jsonArray); // TODO remove unnecessary serialization validationEvent = ((JObject)events[0]["data"]).ToObject <SubscriptionValidationEvent>(); SubscriptionValidationResponse validationResponse = new SubscriptionValidationResponse { ValidationResponse = validationEvent.ValidationCode }; var returnMessage = new HttpResponseMessage(HttpStatusCode.OK); returnMessage.Content = new StringContent(JsonConvert.SerializeObject(validationResponse)); _tracer.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, $"perform handshake with eventGrid for function: {functionName}")); return(returnMessage); } else if (String.Equals(eventTypeHeader, "Notification", StringComparison.OrdinalIgnoreCase)) { JArray events = null; string requestContent = await req.Content.ReadAsStringAsync(); var token = JToken.Parse(requestContent); if (token.Type == JTokenType.Array) { // eventgrid schema events = (JArray)token; } else if (token.Type == JTokenType.Object) { // cloudevent schema events = new JArray { token }; } List <Task <FunctionResult> > executions = new List <Task <FunctionResult> >(); foreach (var ev in events) { // assume each event is a JObject TriggeredFunctionData triggerData = new TriggeredFunctionData { TriggerValue = ev }; executions.Add(_listeners[functionName].Executor.TryExecuteAsync(triggerData, CancellationToken.None)); } await Task.WhenAll(executions); // FIXME without internal queuing, we are going to process all events in parallel // and return 500 if there's at least one failure...which will cause EventGrid to resend the entire payload foreach (var execution in executions) { if (!execution.Result.Succeeded) { return(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent(execution.Result.Exception.Message) }); } } return(new HttpResponseMessage(HttpStatusCode.Accepted)); } else if (String.Equals(eventTypeHeader, "Unsubscribe", StringComparison.OrdinalIgnoreCase)) { // TODO disable function? return(new HttpResponseMessage(HttpStatusCode.Accepted)); } return(new HttpResponseMessage(HttpStatusCode.BadRequest)); }
public static async Task <HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { var url = string.Empty; var stopwatch = Stopwatch.StartNew(); var jsonResponse = string.Empty; try { var reqBodyStr = await req.Content.ReadAsStringAsync(); var reqBody = JsonConvert.DeserializeObject <URLHolder>(reqBodyStr); url = reqBody.Url; if (!string.IsNullOrEmpty(reqBody.Parameter)) { url += reqBody.Parameter; } log.Info("RSS " + url); // TODO: use HttpCachedService (also as means of failover if the RSS stream is down) string data = await client.GetStringAsync(reqBody.Url.ToString()); jsonResponse = ParseRSS(data); if (log.Level == TraceLevel.Verbose) { log.Trace(new TraceEvent(TraceLevel.Verbose, $"Successfully transformed '{url}' '{data}' to '{jsonResponse}'")); } else { log.Info($"Successfully transformed '{url}'"); } } catch (HttpRequestException hre) { var msg = $"RSS Featurization failed '{url}' for '{req.RequestUri.ToString()}': '{hre.Message}'"; log.Warning(msg); // TODO: maybe switch to dependency w/ status failed? Services.TelemetryClient.TrackEvent(msg, new Dictionary <string, string> { { "Service", req.RequestUri.ToString() }, { "Url", url }, { "Exception", hre.Message } }); } catch (Exception ex) { log.Error($"Failed to process '{url}'", ex); Services.TelemetryClient.TrackException( ex, new Dictionary <string, string> { { "Service", req.RequestUri.ToString() }, { "Url", url } }); // swallow the error message and return empty. That way we can differentiate between real outages // remote errors } finally { Services.TelemetryClient.TrackEvent($"RSS {url}", metrics: new Dictionary <string, double> { { "requestTime", stopwatch.ElapsedMilliseconds } }); } return(new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StringContent( jsonResponse, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), "application/json") }); }
private Dictionary <string, object> CreateScriptExecutionContext(object input, DataType dataType, TraceWriter traceWriter, FunctionInvocationContext invocationContext) { // create a TraceWriter wrapper that can be exposed to Node.js var log = (Func <object, Task <object> >)(p => { var logData = (IDictionary <string, object>)p; string message = (string)logData["msg"]; if (message != null) { try { TraceLevel level = (TraceLevel)logData["lvl"]; var evt = new TraceEvent(level, message); traceWriter.Trace(evt); } catch (ObjectDisposedException) { // if a function attempts to write to a disposed // TraceWriter. Might happen if a function tries to // log after calling done() } } return(Task.FromResult <object>(null)); }); var bindings = new Dictionary <string, object>(); var bind = (Func <object, Task <object> >)(p => { IDictionary <string, object> bindValues = (IDictionary <string, object>)p; foreach (var bindValue in bindValues) { bindings[bindValue.Key] = bindValue.Value; } return(Task.FromResult <object>(null)); }); var context = new Dictionary <string, object>() { { "invocationId", invocationContext.ExecutionContext.InvocationId }, { "log", log }, { "bindings", bindings }, { "bind", bind } }; if (!string.IsNullOrEmpty(_entryPoint)) { context["_entryPoint"] = _entryPoint; } if (input is HttpRequestMessage) { // convert the request to a json object HttpRequestMessage request = (HttpRequestMessage)input; string rawBody = null; var requestObject = CreateRequestObject(request, out rawBody); input = requestObject; if (rawBody != null) { requestObject["rawBody"] = rawBody; } // If this is a WebHook function, the input should be the // request body HttpTriggerBindingMetadata httpBinding = _trigger as HttpTriggerBindingMetadata; if (httpBinding != null && !string.IsNullOrEmpty(httpBinding.WebHookType)) { requestObject.TryGetValue("body", out input); } // make the entire request object available as well // this is symmetric with context.res which we also support context["req"] = requestObject; } else if (input is TimerInfo) { // TODO: Need to generalize this model rather than hardcode // so other extensions can also express their Node.js object model TimerInfo timerInfo = (TimerInfo)input; var inputValues = new Dictionary <string, object>() { { "isPastDue", timerInfo.IsPastDue } }; if (timerInfo.ScheduleStatus != null) { inputValues["last"] = timerInfo.ScheduleStatus.Last.ToString("s", CultureInfo.InvariantCulture); inputValues["next"] = timerInfo.ScheduleStatus.Next.ToString("s", CultureInfo.InvariantCulture); } input = inputValues; } else if (input is Stream) { FunctionBinding.ConvertStreamToValue((Stream)input, dataType, ref input); } Utility.ApplyBindingData(input, invocationContext.Binder.BindingData); var bindingData = NormalizeBindingData(invocationContext.Binder.BindingData); bindingData["invocationId"] = invocationContext.ExecutionContext.InvocationId.ToString(); context["bindingData"] = bindingData; // if the input is json, try converting to an object or array object converted; if (TryConvertJson(input, out converted)) { input = converted; } bindings.Add(_trigger.Name, input); context.Add("_triggerType", _trigger.Type); return(context); }
private void Trace(string message, TraceLevel level) { _traceWriter?.Trace($"File watcher: ('{_path}') - {message}", level, null); }
public override void Trace(TraceEvent traceEvent) { _innerWriter.Trace(traceEvent); }
private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty) { if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) { return(true); } ReferenceLoopHandling?referenceLoopHandling = null; if (property != null) { referenceLoopHandling = property.ReferenceLoopHandling; } if (referenceLoopHandling == null && containerProperty != null) { referenceLoopHandling = containerProperty.ItemReferenceLoopHandling; } if (referenceLoopHandling == null && containerContract != null) { referenceLoopHandling = containerContract.ItemReferenceLoopHandling; } if (_serializeStack.IndexOf(value) != -1) { var serializerReferenceLoopHandling = referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling); if (serializerReferenceLoopHandling == ReferenceLoopHandling.Error) { string message; if (property == null) { message = "Self referencing loop detected with type {0}, Path: {1}".FormatWith(CultureInfo.InvariantCulture, value.GetType(), writer.Path); } else { message = "Self referencing loop detected in {0}. Consider applying [JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Ignore] to property {1}." .FormatWith(CultureInfo.InvariantCulture, writer.Path, property.PropertyName); } throw new JsonSerializationException(message); } else { string message = "Self referencing loop detected"; if (property != null) { message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName); } message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()); switch (serializerReferenceLoopHandling) { case ReferenceLoopHandling.Ignore: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Skipping serializing self referenced value."), null); } return(false); case ReferenceLoopHandling.Serialize: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Serializing self referenced value."), null); } return(true); } } } return(true); }
private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty) { if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) { return(true); } ReferenceLoopHandling?referenceLoopHandling = null; if (property != null) { referenceLoopHandling = property.ReferenceLoopHandling; } if (referenceLoopHandling == null && containerProperty != null) { referenceLoopHandling = containerProperty.ItemReferenceLoopHandling; } if (referenceLoopHandling == null && containerContract != null) { referenceLoopHandling = containerContract.ItemReferenceLoopHandling; } bool exists = (Serializer._equalityComparer != null) ? _serializeStack.Contains(value, Serializer._equalityComparer) : _serializeStack.Contains(value); if (exists) { string message = "Self referencing loop detected"; if (property != null) { message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName); } message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()); switch (referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling)) { case ReferenceLoopHandling.Error: throw JsonSerializationException.Create(null, writer.ContainerPath, message, null); case ReferenceLoopHandling.Ignore: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Skipping serializing self referenced value."), null); } return(false); case ReferenceLoopHandling.Serialize: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Serializing self referenced value."), null); } return(true); } } return(true); }
private void Trace(string message, TraceLevel level) { _traceWriter?.Trace($"{message} (path: '{_path}')", level, null); }
private async Task <Dictionary <string, object> > CreateScriptExecutionContextAsync(object input, DataType dataType, TraceWriter traceWriter, FunctionInvocationContext invocationContext) { // create a TraceWriter wrapper that can be exposed to Node.js var log = (ScriptFunc)(p => { var logData = (IDictionary <string, object>)p; string message = (string)logData["msg"]; if (message != null) { try { TraceLevel level = (TraceLevel)logData["lvl"]; var evt = new TraceEvent(level, message); // Node captures the AsyncLocal value of the first invocation, which means that logs // are correlated incorrectly. Here we'll overwrite that value with the correct value // immediately before logging. using (invocationContext.Logger.BeginScope( new Dictionary <string, object> { ["MS_FunctionInvocationId"] = invocationContext.ExecutionContext.InvocationId })) { // TraceWriter already logs to ILogger traceWriter.Trace(evt); } } catch (ObjectDisposedException) { // if a function attempts to write to a disposed // TraceWriter. Might happen if a function tries to // log after calling done() } } return(Task.FromResult <object>(null)); }); var bindings = new Dictionary <string, object>(); var bind = (ScriptFunc)(p => { IDictionary <string, object> bindValues = (IDictionary <string, object>)p; foreach (var bindValue in bindValues) { bindings[bindValue.Key] = bindValue.Value; } return(Task.FromResult <object>(null)); }); var executionContext = new Dictionary <string, object> { ["invocationId"] = invocationContext.ExecutionContext.InvocationId, ["functionName"] = invocationContext.ExecutionContext.FunctionName, ["functionDirectory"] = invocationContext.ExecutionContext.FunctionDirectory, }; var context = new Dictionary <string, object>() { { "invocationId", invocationContext.ExecutionContext.InvocationId }, { "executionContext", executionContext }, { "log", log }, { "bindings", bindings }, { "bind", bind } }; if (!string.IsNullOrEmpty(_entryPoint)) { context["_entryPoint"] = _entryPoint; } // convert the request to a json object if (input is HttpRequestMessage request) { var requestObject = await CreateRequestObjectAsync(request).ConfigureAwait(false); input = requestObject; // If this is a WebHook function, the input should be the // request body var httpTrigger = _inputBindings.OfType <ExtensionBinding>().SingleOrDefault(p => p.Metadata.IsTrigger)? .Attributes.OfType <HttpTriggerAttribute>().SingleOrDefault(); if (httpTrigger != null && !string.IsNullOrEmpty(httpTrigger.WebHookType)) { requestObject.TryGetValue("body", out input); } // make the entire request object available as well // this is symmetric with context.res which we also support context["req"] = requestObject; } else if (input is TimerInfo) { // TODO: Need to generalize this model rather than hardcode // so other extensions can also express their Node.js object model TimerInfo timerInfo = (TimerInfo)input; var inputValues = new Dictionary <string, object>() { { "isPastDue", timerInfo.IsPastDue } }; if (timerInfo.ScheduleStatus != null) { inputValues["last"] = timerInfo.ScheduleStatus.Last.ToString("s", CultureInfo.InvariantCulture); inputValues["next"] = timerInfo.ScheduleStatus.Next.ToString("s", CultureInfo.InvariantCulture); } input = inputValues; } else if (input is Stream) { FunctionBinding.ConvertStreamToValue((Stream)input, dataType, ref input); } Utility.ApplyBindingData(input, invocationContext.Binder.BindingData); var bindingData = NormalizeBindingData(invocationContext.Binder.BindingData); bindingData["invocationId"] = invocationContext.ExecutionContext.InvocationId.ToString(); context["bindingData"] = bindingData; // if the input is json, try converting to an object or array object converted; if (TryConvertJson(input, out converted)) { input = converted; } bindings.Add(_trigger.Name, input); context.Add("_triggerType", _trigger.Type); return(context); }
public async Task <BlobContent> PostAsync(TraceWriter log, string site, string id, object request, bool forceRefresh, CancellationToken cancellationToken) { await this.InitializeAsync(); var stopwatch = Stopwatch.StartNew(); var cacheHit = true; HttpResponseMessage responseMessage = null; string body = null; try { body = request as string; string input; string contentType; if (body != null) { // if this is a raw string, we need to escape for storage input = JsonConvert.SerializeObject(request); contentType = "text/plain"; } else { body = JsonConvert.SerializeObject(request); input = body; contentType = "application/json"; } log.Trace(new TraceEvent(TraceLevel.Verbose, $"Requesting {this.containerName} at {this.endpoint}: {body}")); var blobCache = new BlobCache(this.storageConnectionString); // lookup Azure Blob storage cache first // have a 5min timeout for retries BlobContent blobContent = null; if (!forceRefresh) { blobContent = await blobCache.GetAsync(site, id, this.containerName, input, TimeSpan.FromMinutes(5), cancellationToken); } if (blobContent == null) { cacheHit = false; var stopwatchReqeust = Stopwatch.StartNew(); // make the actual HTTP request responseMessage = await this.client.PostAsync( string.Empty, new StringContent( body, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), contentType)); Services.TelemetryClient.TrackDependency(this.containerName, this.endpoint, this.containerName, null, DateTime.UtcNow, stopwatchReqeust.Elapsed, $"{responseMessage.StatusCode} {responseMessage.ReasonPhrase}", responseMessage.IsSuccessStatusCode); log.Trace(new TraceEvent(TraceLevel.Verbose, $"Response: {responseMessage.StatusCode} {responseMessage.ReasonPhrase}")); if (!responseMessage.IsSuccessStatusCode) { blobContent = new BlobContent { // TODO: random expiration Expires = DateTime.UtcNow + TimeSpan.FromMinutes(1), }; } else { var responseStr = await responseMessage.Content.ReadAsStringAsync(); log.Trace(new TraceEvent(TraceLevel.Verbose, $"Result {this.containerName} at {this.endpoint}: {responseStr}")); // once we got a response, cache for 3 days // TODO: add configuration option // TODO: add force refresh parameter blobContent = await blobCache.PersistAsync(site, id, this.containerName, input, responseStr, TimeSpan.FromDays(3), cancellationToken); } } return(blobContent); } finally { var props = new Dictionary <string, string> { { "site", site }, { "id", id }, { "cacheHit", cacheHit.ToString() }, { "StatusCode", responseMessage?.StatusCode.ToString() }, { "Reason", responseMessage?.ReasonPhrase } }; var sb = new StringBuilder(this.containerName); if (responseMessage != null && responseMessage.StatusCode != System.Net.HttpStatusCode.OK) { props.Add("Request", body); sb.Append(" failed"); } Services.TelemetryClient.TrackEvent( sb.ToString(), props, metrics: new Dictionary <string, double> { { "requestTime", stopwatch.ElapsedMilliseconds } }); } }
internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Type objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter"); // set serialization options onto writer Formatting?previousFormatting = null; if (_formatting != null && jsonWriter.Formatting != _formatting) { previousFormatting = jsonWriter.Formatting; jsonWriter.Formatting = _formatting.Value; } DateFormatHandling?previousDateFormatHandling = null; if (_dateFormatHandling != null && jsonWriter.DateFormatHandling != _dateFormatHandling) { previousDateFormatHandling = jsonWriter.DateFormatHandling; jsonWriter.DateFormatHandling = _dateFormatHandling.Value; } DateTimeZoneHandling?previousDateTimeZoneHandling = null; if (_dateTimeZoneHandling != null && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.Value; } FloatFormatHandling?previousFloatFormatHandling = null; if (_floatFormatHandling != null && jsonWriter.FloatFormatHandling != _floatFormatHandling) { previousFloatFormatHandling = jsonWriter.FloatFormatHandling; jsonWriter.FloatFormatHandling = _floatFormatHandling.Value; } StringEscapeHandling?previousStringEscapeHandling = null; if (_stringEscapeHandling != null && jsonWriter.StringEscapeHandling != _stringEscapeHandling) { previousStringEscapeHandling = jsonWriter.StringEscapeHandling; jsonWriter.StringEscapeHandling = _stringEscapeHandling.Value; } CultureInfo previousCulture = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { previousCulture = jsonWriter.Culture; jsonWriter.Culture = _culture; } string previousDateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { previousDateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } TraceJsonWriter traceJsonWriter = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null; JsonSerializerInternalWriter serializerWriter = new JsonSerializerInternalWriter(this); serializerWriter.Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) { TraceWriter.Trace(TraceLevel.Verbose, "Serialized JSON: " + Environment.NewLine + traceJsonWriter.GetJson(), null); } // reset writer back to previous options if (previousFormatting != null) { jsonWriter.Formatting = previousFormatting.Value; } if (previousDateFormatHandling != null) { jsonWriter.DateFormatHandling = previousDateFormatHandling.Value; } if (previousDateTimeZoneHandling != null) { jsonWriter.DateTimeZoneHandling = previousDateTimeZoneHandling.Value; } if (previousFloatFormatHandling != null) { jsonWriter.FloatFormatHandling = previousFloatFormatHandling.Value; } if (previousStringEscapeHandling != null) { jsonWriter.StringEscapeHandling = previousStringEscapeHandling.Value; } if (_dateFormatStringSet) { jsonWriter.DateFormatString = previousDateFormatString; } if (previousCulture != null) { jsonWriter.Culture = previousCulture; } }
public static async Task <HttpResponseMessage> IdentifyCustomer([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req, TraceWriter log) { // Get request body var body = await req.Content.ReadAsStringAsync(); var imageCapture = JsonConvert.DeserializeObject <IdentifyCustomerRequest>(body, new JsonConverter[] { new GuidJsonConverter() }); if (imageCapture == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, "No Valid Data submitted.")); } // Decode data from Base64 byte[] imageBytes = Convert.FromBase64String(imageCapture.Image); // Detect the faces Face detectedFace; using (var stream = new MemoryStream(imageBytes)) { detectedFace = await FaceClient.Instance.DetectPrimaryFace(stream, true); if (detectedFace == null || detectedFace.FaceId == null) { req.CreateResponse(HttpStatusCode.ExpectationFailed, "Error: No face was detected"); } } // Crop the face var rect = new Rectangle( detectedFace.FaceRectangle.Left, detectedFace.FaceRectangle.Top, detectedFace.FaceRectangle.Width, detectedFace.FaceRectangle.Height ); rect.Inflate(50, 50); using (var stream = new MemoryStream(imageBytes)) { Bitmap bmp = Image.FromStream(stream) as Bitmap; var cropped = ImageUtils.CropBitmap(bmp, rect); imageBytes = cropped.ToByteArray(ImageFormat.Png); } // Store the image string storedUrl = StorageClient.Instance.StoreImage(imageBytes, ImagesContainerID)?.ToString(); log.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Verbose, "heres the url!: " + storedUrl)); var response = new IdentifyCustomerResponse() { ImageUrl = storedUrl, Emotion = FaceClient.Instance.ParseEmotions(detectedFace.FaceAttributes.Emotion) }; // Check for existing Customers response.Customer = await FaceClient.Instance.IdentifyCustomerFace(detectedFace.FaceId); // Update the customers history with the recent photo if (response.Customer != null) { await FaceClient.Instance.AddCustomerFace(response.Customer, storedUrl); // Get their previous order var orders = CosmosClient.Instance.GetCustomerOrders(response.Customer.id, 1); // Could show more if we wanted response.PreviousOrder = orders.FirstOrDefault(); } // If there are no matched customers return a new Customer with the FaceID else { response.Customer = new Customer() { FaceId = detectedFace.FaceId, Age = detectedFace.FaceAttributes.Age, Gender = detectedFace.FaceAttributes.Gender }; } return(req.CreateResponse(HttpStatusCode.OK, response)); }