private void LogFunctionResult(IEnumerable <KeyValuePair <string, object> > state, LogLevel logLevel, Exception exception)
        {
            IDictionary <string, object> scopeProps = DictionaryLoggerScope.GetMergedStateDictionary() ?? new Dictionary <string, object>();

            // log associated exception details
            KeyValuePair <string, object>[] stateProps = state as KeyValuePair <string, object>[] ?? state.ToArray();
            if (exception != null)
            {
                LogException(logLevel, stateProps, exception, null);
            }

            ApplyFunctionResultActivityTags(stateProps, scopeProps);

            IOperationHolder <RequestTelemetry> requestOperation = (IOperationHolder <RequestTelemetry>)scopeProps.GetValueOrDefault(OperationContext);

            if (requestOperation != null)
            {
                // We somehow never started the operation, perhaps, it was auto-tracked by the AI SDK
                // so there's no way to complete it.

                RequestTelemetry requestTelemetry = requestOperation.Telemetry;
                requestTelemetry.Success      = exception == null;
                requestTelemetry.ResponseCode = "0";

                // Note: we do not have to set Duration, StartTime, etc. These are handled by the call to Stop()
                _telemetryClient.StopOperation(requestOperation);
            }
        }
        // Applies scope properties; filters most system properties, which are used internally
        private static void ApplyScopeProperties(ISupportProperties telemetry)
        {
            var scopeProperties = DictionaryLoggerScope.GetMergedStateDictionary();

            var customScopeProperties = scopeProperties.Where(p => !SystemScopeKeys.Contains(p.Key, StringComparer.Ordinal));

            ApplyProperties(telemetry, customScopeProperties, LogConstants.CustomPropertyPrefix);
        }
        public IDisposable BeginScope <TState>(TState state)
        {
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }

            StartTelemetryIfFunctionInvocation(state as IDictionary <string, object>);

            return(DictionaryLoggerScope.Push(state));
        }
        public static IDisposable Push(object state)
        {
            IDictionary <string, object> stateValues;

            if (state is IEnumerable <KeyValuePair <string, object> > stateEnum)
            {
                // Convert this to a dictionary as we have scenarios where we cannot have duplicates. In this
                // case, if there are dupes, the later entry wins.
                stateValues = new Dictionary <string, object>();
                foreach (var entry in stateEnum)
                {
                    stateValues[entry.Key] = entry.Value;
                }
            }
            else
            {
                // There's nothing we can do with other states.
                return(null);
            }

            Current = new DictionaryLoggerScope(new ReadOnlyDictionary <string, object>(stateValues), Current);
            return(new DisposableScope());
        }
 private DictionaryLoggerScope(IReadOnlyDictionary <string, object> state, DictionaryLoggerScope parent)
 {
     State  = state;
     Parent = parent;
 }