コード例 #1
0
        //--- Extension Methods ---

        /// <summary>
        /// Log a debugging message. This message will only appear in the log and will not be forwarded to an error aggregator.
        /// </summary>
        /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
        /// <param name="format">The message format string. If not arguments are supplied, the message format string will be printed as a plain string.</param>
        /// <param name="arguments">Optional arguments for the message string.</param>
        /// <seealso cref="LambdaLogLevel"/>
        public static void LogDebug(this ILambdaSharpLogger logger, string format, params object[] arguments)
        {
            if (logger.DebugLoggingEnabled)
            {
                logger.Log(LambdaLogLevel.DEBUG, exception: null, format: format, arguments: arguments);
            }
        }
コード例 #2
0
ファイル: UnzipLogic.cs プロジェクト: jhart0/LambdaSharpTool
 //--- Constructors ---
 public UnzipLogic(ILambdaSharpLogger logger, string manifestBucket, IAmazonS3 s3Client)
 {
     _logger          = logger;
     _manifestBucket  = manifestBucket;
     _s3Client        = new AmazonS3Client();
     _transferUtility = new TransferUtility(_s3Client);
 }
コード例 #3
0
 /// <summary>
 /// Log a CloudWatch metric. The metric is picked up by CloudWatch logs and automatically ingested as a CloudWatch metric.
 /// </summary>
 /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
 /// <param name="name">Metric name.</param>
 /// <param name="value">Metric value.</param>
 /// <param name="unit">Metric unit.</param>
 /// <param name="dimensionNames">Metric dimensions as comma-separated list (e.g. [ "A", "A,B" ]).</param>
 /// <param name="dimensionValues">Dictionary of dimesion name-value pairs.</param>
 public static void LogMetric(
     this ILambdaSharpLogger logger,
     string name,
     double value,
     LambdaMetricUnit unit,
     IEnumerable <string> dimensionNames,
     Dictionary <string, string> dimensionValues
     ) => logger.LogMetric(new[] { new LambdaMetric(name, value, unit) }, dimensionNames, dimensionValues);
コード例 #4
0
 //--- Constructors ---
 public LambdaRobotsBotClient(string botId, string lambdaArn, TimeSpan requestTimeout, IAmazonLambda lambdaClient = null, ILambdaSharpLogger logger = null)
 {
     _botId          = botId ?? throw new ArgumentNullException(nameof(botId));
     _lambdaArn      = lambdaArn ?? throw new ArgumentNullException(nameof(lambdaArn));
     _requestTimeout = requestTimeout;
     _lambdaClient   = lambdaClient ?? new AmazonLambdaClient();
     _logger         = logger;
 }
コード例 #5
0
        /// <summary>
        /// Send a CloudWatch event with optional event details and resources it applies to. This event is forwarded to the configured EventBridge.
        /// </summary>
        /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
        /// <param name="source">Name of the event source.</param>
        /// <param name="detailType">Free-form string used to decide what fields to expect in the event detail.</param>
        /// <param name="detail">Data-structure to serialize as a JSON string. If value is already a <code>string</code>, it is sent as-is. There is no other schema imposed. The data-structure may contain fields and nested subobjects.</param>
        /// <param name="resources">Optional AWS or custom resources, identified by unique identifier (e.g. ARN), which the event primarily concerns. Any number, including zero, may be present.</param>
        public static void LogEvent <T>(this ILambdaSharpLogger logger, string source, string detailType, T detail, IEnumerable <string> resources = null)
        {
            // augment event resources with LambdaSharp specific resources
            var lambdaResources = new List <string>();

            if (resources != null)
            {
                lambdaResources.AddRange(resources);
            }
            if (logger.Info.ModuleId != null)
            {
                lambdaResources.Add($"lambdasharp:stack:{logger.Info.ModuleId}");
            }
            var moduleFullName = logger.Info.GetModuleFullName();

            if (moduleFullName != null)
            {
                lambdaResources.Add($"lambdasharp:module:{moduleFullName}");
            }
            if (logger.Info.DeploymentTier != null)
            {
                lambdaResources.Add($"lambdasharp:tier:{logger.Info.DeploymentTier}");
            }
            if (logger.Info.ModuleInfo != null)
            {
                lambdaResources.Add($"lambdasharp:moduleinfo:{logger.Info.ModuleInfo}");
            }
            var moduleOrigin = logger.Info.GetModuleOrigin();

            if (moduleOrigin != null)
            {
                lambdaResources.Add($"lambdasharp:origin:{moduleOrigin}");
            }
            if (logger.Info.AppId != null)
            {
                lambdaResources.Add($"lambdasharp:app:{logger.Info.AppId}");
            }

            // create event record for logging
            var eventRecord = new LambdaEventRecord {
                EventBus   = "default",
                Source     = source,
                DetailType = detailType,
                Detail     = (detail is string detailText)
                    ? detailText
                    : JsonSerializer.Serialize(detail, JsonSerializerOptions),
                Resources = lambdaResources
            };

            eventRecord.SetTime(DateTimeOffset.UtcNow);
            logger.LogRecord(eventRecord);
        }
    }
コード例 #6
0
        //--- Extension Methods ---

        /// <summary>
        /// Send a CloudWatch event with optional event details and resources it applies to. This event is forwarded to the configured EventBridge. The 'detail-type' property is set to the full type name of the detail value.
        /// </summary>
        /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
        /// <param name="source">Name of the event source.</param>
        /// <param name="detail">Data-structure to serialize as a JSON string. If value is already a <code>string</code>, it is sent as-is. There is no other schema imposed. The data-structure may contain fields and nested subobjects.</param>
        /// <param name="resources">Optional AWS or custom resources, identified by unique identifier (e.g. ARN), which the event primarily concerns. Any number, including zero, may be present.</param>
        public static void LogEvent <T>(this ILambdaSharpLogger logger, string source, T detail, IEnumerable <string> resources = null)
        => LogEvent <T>(logger, source, typeof(T).FullName, detail, resources);
コード例 #7
0
        /// <summary>
        /// Log a CloudWatch metric. The metric is picked up by CloudWatch logs and automatically ingested as a CloudWatch metric.
        /// </summary>
        /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
        /// <param name="metrics">Enumeration of metrics, including their name, value, and unit.</param>
        /// <param name="dimensionNames">Metric dimensions as comma-separated list (e.g. [ "A", "A,B" ]).</param>
        /// <param name="dimensionValues">Dictionary of dimesion name-value pairs.</param>
        public static void LogMetric(
            this ILambdaSharpLogger logger,
            IEnumerable <LambdaMetric> metrics,
            IEnumerable <string> dimensionNames,
            Dictionary <string, string> dimensionValues
            )
        {
            if (!metrics.Any())
            {
                return;
            }
            IEnumerable <string>        newDimensionNames;
            Dictionary <string, string> newDimensionValues;

            if (logger.Info.ModuleId != null)
            {
                if (logger.Info.FunctionName != null)
                {
                    // dimension the metric by 'Stack' and 'Function'
                    newDimensionNames  = dimensionNames.Union(new[] { "Stack", "Stack,Function" }).Distinct().ToList();
                    newDimensionValues = new Dictionary <string, string>(dimensionValues)
                    {
                        ["Stack"]    = logger.Info.ModuleId,
                        ["Function"] = logger.Info.FunctionName
                    };
                }
                else if (logger.Info.AppName != null)
                {
                    // dimension the metric by 'Stack' and 'App'
                    newDimensionNames  = dimensionNames.Union(new[] { "Stack", "Stack,App" }).Distinct().ToList();
                    newDimensionValues = new Dictionary <string, string>(dimensionValues)
                    {
                        ["Stack"] = logger.Info.ModuleId,
                        ["App"]   = logger.Info.AppName
                    };
                }
                else
                {
                    newDimensionNames  = new List <string>();
                    newDimensionValues = new Dictionary <string, string>(dimensionValues);
                }
            }
            else
            {
                if (logger.Info.FunctionName != null)
                {
                    // dimension the metric by 'Function' only
                    newDimensionNames  = dimensionNames.Union(new[] { "Function" }).Distinct().ToList();
                    newDimensionValues = new Dictionary <string, string>(dimensionValues)
                    {
                        ["Function"] = logger.Info.FunctionName
                    };
                }
                else if (logger.Info.AppName != null)
                {
                    // dimension the metric by 'App' only
                    newDimensionNames  = dimensionNames.Union(new[] { "App" }).Distinct().ToList();
                    newDimensionValues = new Dictionary <string, string>(dimensionValues)
                    {
                        ["App"] = logger.Info.AppName
                    };
                }
                else
                {
                    newDimensionNames  = new List <string>();
                    newDimensionValues = new Dictionary <string, string>(dimensionValues);
                }
            }

            // add git sha and git branch as extra metadata when available
            if (logger.Info.GitSha != null)
            {
                newDimensionValues["GitSha"] = logger.Info.GitSha;
            }
            if (logger.Info.GitBranch != null)
            {
                newDimensionValues["GitBranch"] = logger.Info.GitBranch;
            }
            logger.LogMetric($"Module:{logger.Info.GetModuleFullName()}", metrics, newDimensionNames, newDimensionValues);
        }
コード例 #8
0
 /// <summary>
 /// Log a CloudWatch metric. The metric is picked up by CloudWatch logs and automatically ingested as a CloudWatch metric.
 /// </summary>
 /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
 /// <param name="metrics">Enumeration of metrics, including their name, value, and unit.</param>
 public static void LogMetric(this ILambdaSharpLogger logger, IEnumerable <LambdaMetric> metrics)
 => logger.LogMetric(metrics, Array.Empty <string>(), new Dictionary <string, string>());
コード例 #9
0
        //--- Extension Methods ---

        /// <summary>
        /// Log a CloudWatch metric. The metric is picked up by CloudWatch logs and automatically ingested as a CloudWatch metric.
        /// </summary>
        /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
        /// <param name="name">Metric name.</param>
        /// <param name="value">Metric value.</param>
        /// <param name="unit">Metric unit.</param>
        public static void LogMetric(
            this ILambdaSharpLogger logger,
            string name,
            double value,
            LambdaMetricUnit unit
            ) => logger.LogMetric(new[] { new LambdaMetric(name, value, unit) });
コード例 #10
0
        /// <summary>
        /// Log a CloudWatch metric. The metric is picked up by CloudWatch logs and automatically ingested as a CloudWatch metric.
        /// </summary>
        /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
        /// <param name="namespace">Metric namespace.</param>
        /// <param name="metrics">Enumeration of metrics, including their name, value, and unit.</param>
        /// <param name="dimensionNames">Metric dimensions as comma-separated list (e.g. [ "A", "A,B" ]).</param>
        /// <param name="dimensionValues">Dictionary of dimesion name-value pairs.</param>
        public static void LogMetric(
            this ILambdaSharpLogger logger,
            string @namespace,
            IEnumerable <LambdaMetric> metrics,
            IEnumerable <string> dimensionNames,
            Dictionary <string, string> dimensionValues
            )
        {
            if (!metrics.Any())
            {
                // nothing to do
                return;
            }
            if (dimensionNames.Count() > 9)
            {
                throw new ArgumentException("metric cannot exceed 9 dimensions", nameof(dimensionNames));
            }
            var targets = new Dictionary <string, object>();

            // validate and process metrics
            var index = 0;

            foreach (var metric in metrics)
            {
                if (string.IsNullOrEmpty(metric.Name))
                {
                    throw new ArgumentException($"metric name cannot be empty (index {index})");
                }
                AssertNotReservedName(metric.Name, "metric");
                if (double.IsNaN(metric.Value) || double.IsNegativeInfinity(metric.Value) || double.IsPositiveInfinity(metric.Value))
                {
                    // these values are rejected by CloudWatch metrics
                    throw new ArgumentException($"metric '{metric.Name}' has an out-of-range value");
                }
                if (!targets.TryAdd(metric.Name, metric.Value))
                {
                    throw new ArgumentException($"conflicting metric name: {metric.Name}");
                }
                ++index;
            }

            // validate and process dimension values
            index = 0;
            foreach (var dimensionValue in dimensionValues)
            {
                if (string.IsNullOrEmpty(dimensionValue.Key))
                {
                    throw new ArgumentException($"dimension name cannot be empty (index {index})");
                }
                if (string.IsNullOrEmpty(dimensionValue.Value))
                {
                    throw new ArgumentException($"dimension value cannot be empty (index {index})");
                }
                AssertNotReservedName(dimensionValue.Key, "dimension");
                if (!targets.TryAdd(dimensionValue.Key, dimensionValue.Value))
                {
                    throw new ArgumentException($"conflicting dimension name: {dimensionValue.Key}");
                }
                ++index;
            }

            // validate and process metric dimensions
            var metricDimensions = dimensionNames
                                   .Select(dimension => dimension
                                           .Split(',')
                                           .Select(dim => dim.Trim())
                                           .ToList()
                                           )
                                   .ToList();

            foreach (var metricDimension in metricDimensions.SelectMany(dimension => dimension))
            {
                if (!dimensionValues.ContainsKey(metricDimension))
                {
                    throw new ArgumentException($"missing dimension value: {metricDimension}");
                }
            }

            // create embedded metrics data-structure:
            var record = new LambdaMetricsRecord {
                Aws = new EmbeddedCloudWatchMetrics {
                    CloudWatchMetrics =
                    {
                        new CloudWatchMetrics {
                            Namespace  = @namespace,
                            Dimensions = metricDimensions,
                            Metrics    = metrics.Select(metric => new CloudWatchMetricValue {
                                Name = metric.Name,
                                Unit = ConvertUnit(metric.Unit)
                            }).ToList()
                        }
                    }
                },
                TargetMembers = targets
            };

            // log metric record
            logger.LogRecord(record);

            // local functions
            void AssertNotReservedName(string name, string parameterType)
            {
                switch (name)
                {
                case "_aws":
                case "Source":
                case "Version":
                    throw new ArgumentException($"{parameterType} name cannot be named '{name}'");

                default:
                    break;
                }
            }

            string ConvertUnit(LambdaMetricUnit unit)
            {
                switch (unit)
                {
                // these enum names need to be mapped to their correct CloudWatch metrics unit counterpart
                case LambdaMetricUnit.BytesPerSecond:
                    return("Bytes/Second");

                case LambdaMetricUnit.KilobytesPerSecond:
                    return("Kilobytes/Second");

                case LambdaMetricUnit.MegabytesPerSecond:
                    return("Megabytes/Second");

                case LambdaMetricUnit.GigabytesPerSecond:
                    return("Gigabytes/Second");

                case LambdaMetricUnit.TerabytesPerSecond:
                    return("Terabytes/Second");

                case LambdaMetricUnit.BitsPerSecond:
                    return("Bits/Second");

                case LambdaMetricUnit.KilobitsPerSecond:
                    return("Kilobits/Second");

                case LambdaMetricUnit.MegabitsPerSecond:
                    return("Megabits/Second");

                case LambdaMetricUnit.GigabitsPerSecond:
                    return("Gigabits/Second");

                case LambdaMetricUnit.TerabitsPerSecond:
                    return("Terabits/Second");

                case LambdaMetricUnit.CountPerSecond:
                    return("Count/Second");

                // the remaining enums are good as is
                default:
                    return(unit.ToString());
                }
            }
        }
コード例 #11
0
 /// <summary>
 /// Log an exception as a warning. This message will be reported if an error aggregator is configured for the <c>LambdaSharp.Core</c> module.
 /// </summary>
 /// <remarks>
 /// Only use this method when the exception has no operational impact.
 /// Otherwise, either use <see cref="LogError(ILambdaSharpLogger,Exception)"/>.
 /// </remarks>
 /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
 /// <param name="exception">The exception to log. The exception is logged with its message, stacktrace, and any nested exceptions.</param>
 /// <seealso cref="LambdaLogLevel"/>
 public static void LogErrorAsWarning(this ILambdaSharpLogger logger, Exception exception)
 => logger.Log(LambdaLogLevel.WARNING, exception, exception.Message, Array.Empty <object>());
コード例 #12
0
ファイル: Logic.cs プロジェクト: bgkyer/LambdaSharpTool
 //--- Constructors ---
 public Logic(ILambdaSharpLogger logger)
 {
     _logger = logger ?? throw new ArgumentNullException(nameof(logger));
 }
コード例 #13
0
 /// <summary>
 /// Log an exception as an information message. This message will only appear in the log and will not be forwarded to an error aggregator.
 /// </summary>
 /// <remarks>
 /// Only use this method when the exception has no operational impact.
 /// Otherwise, either use <see cref="LogError(ILambdaSharpLogger,Exception)"/> or <see cref="LogErrorAsWarning(ILambdaSharpLogger,Exception)"/>.
 /// </remarks>
 /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
 /// <param name="exception">The exception to log. The exception is logged with its message, stacktrace, and any nested exceptions.</param>
 /// <seealso cref="LambdaLogLevel"/>
 public static void LogErrorAsInfo(this ILambdaSharpLogger logger, Exception exception)
 => logger.Log(LambdaLogLevel.INFO, exception, exception.Message, Array.Empty <object>());
コード例 #14
0
 /// <summary>
 /// Log an exception with a custom message as an error. This message will be reported if an error aggregator is configured for the <c>LambdaSharp.Core</c> module.
 /// </summary>
 /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
 /// <param name="exception">The exception to log. The exception is logged with its message, stacktrace, and any nested exceptions.</param>
 /// <param name="format">Optional message to use instead of <c>Exception.Message</c>. This parameter can be <c>null</c>.</param>
 /// <param name="arguments">Optional arguments for the <c>format</c> parameter.</param>
 /// <seealso cref="LambdaLogLevel"/>
 public static void LogError(this ILambdaSharpLogger logger, Exception exception, string format, params object[] arguments)
 => logger.Log(LambdaLogLevel.ERROR, exception, format, arguments);
コード例 #15
0
 /// <summary>
 /// Log a warning message. This message will be reported if an error aggregator is configured for the <c>LambdaSharp.Core</c> module.
 /// </summary>
 /// <param name="logger">The <see cref="ILambdaSharpLogger"/> instance to use.</param>
 /// <param name="format">The message format string. If not arguments are supplied, the message format string will be printed as a plain string.</param>
 /// <param name="arguments">Optional arguments for the message string.</param>
 /// <seealso cref="LambdaLogLevel"/>
 public static void LogWarn(this ILambdaSharpLogger logger, string format, params object[] arguments)
 => logger.Log(LambdaLogLevel.WARNING, exception: null, format: format, arguments: arguments);
コード例 #16
0
 //--- Constructors ---
 public WriteJsonLogic(ILambdaSharpLogger logger, IAmazonS3 s3Client, ILambdaSerializer jsonSerializer)
 {
     _logger         = logger ?? throw new ArgumentNullException(nameof(logger));
     _s3Client       = s3Client ?? throw new ArgumentNullException(nameof(s3Client));
     _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer));
 }
コード例 #17
0
 //--- Constructors ---
 public EmptyBucketLogic(ILambdaSharpLogger logger, IAmazonS3 s3Client)
 {
     _logger   = logger;
     _s3Client = s3Client;
 }