/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ using Amazon.Runtime.Internal.Util; using System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Text; using System.Text.RegularExpressions; #if AWS_ASYNC_API using System.Threading.Tasks; #endif using ThirdParty.Json.LitJson; namespace Amazon.Runtime.Internal { /// /// Utility class for CSM. /// Contains logic to serialize CSM events to Json. /// public static class CSMUtilities { private const string requestKey = "Request"; #if AWS_ASYNC_API public static Task SerializetoJsonAndPostOverUDPAsync(MonitoringAPICall monitoringAPICall) { var monitoringAPICallAttempt = monitoringAPICall as MonitoringAPICallAttempt; if (monitoringAPICallAttempt != null) { if (CreateUDPMessage(monitoringAPICallAttempt, out string response)) { return MonitoringListener.Instance.PostMessagesOverUDPAsync(response); } } else { if (CreateUDPMessage((MonitoringAPICallEvent)monitoringAPICall, out string response)) { return MonitoringListener.Instance.PostMessagesOverUDPAsync(response); } } return Task.FromResult(0); } #else public static void BeginSerializetoJsonAndPostOverUDP(MonitoringAPICall monitoringAPICall) { string response = string.Empty; var monitoringAPICallAttempt = monitoringAPICall as MonitoringAPICallAttempt; if (monitoringAPICallAttempt != null) { if (CreateUDPMessage(monitoringAPICallAttempt, out response)) { MonitoringListener.Instance.BeginPostMessagesOverUDPInvoke(response); } } else { if (CreateUDPMessage((MonitoringAPICallEvent)monitoringAPICall, out response)) { MonitoringListener.Instance.BeginPostMessagesOverUDPInvoke(response); } } } #endif public static void SerializetoJsonAndPostOverUDP(MonitoringAPICall monitoringAPICall) { string response = string.Empty; var monitoringAPICallAttempt = monitoringAPICall as MonitoringAPICallAttempt; if (monitoringAPICallAttempt != null) { if (CreateUDPMessage(monitoringAPICallAttempt, out response)) { MonitoringListener.Instance.PostMessagesOverUDP(response); } } else { if (CreateUDPMessage((MonitoringAPICallEvent)monitoringAPICall, out response)) { MonitoringListener.Instance.PostMessagesOverUDP(response); } } } /// /// Method to retrieve the API name from the request name. /// public static string GetApiNameFromRequest(string requestName, IDictionary serviceApiNameMapping, string serviceName) { var logger = Logger.GetLogger(typeof(CSMUtilities)); // Verify that the requestName has the requestKey(Request) as a suffix. if (requestName.EndsWith(requestKey, StringComparison.Ordinal)) { // The API name is extracted from the requestName like so - // PutObjectRequest is converted PutObject by removing the // 'Request' keyword. var apiName = requestName.Substring(0, requestName.Length - requestKey.Length); if (serviceApiNameMapping.Count > 0) { string actualApiName; if(serviceApiNameMapping.TryGetValue(apiName, out actualApiName)) { apiName = actualApiName; } } return apiName; } else { logger.InfoFormat(string.Format(CultureInfo.InvariantCulture, "Invalid request name: Request {0} does not end with the keyword '{1}'. Investigate possible generator bug for service:{2} and operation name:{3}", requestName, requestKey, serviceName, requestName)); return string.Empty; } } /// /// Method to serialize MonitoringAPICallAttempt CSM event to json. /// private static bool CreateUDPMessage(MonitoringAPICallAttempt monitoringAPICallAttempt, out string response) { JsonWriter jw = new JsonWriter(); jw.WriteObjectStart(); jw = CreateUDPMessage(monitoringAPICallAttempt, jw); if (!string.IsNullOrEmpty(monitoringAPICallAttempt.AccessKey)) { jw.WritePropertyName("AccessKey"); jw.Write(monitoringAPICallAttempt.AccessKey); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.AWSException)) { jw.WritePropertyName("AWSException"); jw.Write(monitoringAPICallAttempt.AWSException); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.Fqdn)) { jw.WritePropertyName("Fqdn"); jw.Write(monitoringAPICallAttempt.Fqdn); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.SdkException)) { jw.WritePropertyName("SdkException"); jw.Write(monitoringAPICallAttempt.SdkException); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.AWSExceptionMessage)) { jw.WritePropertyName("AWSExceptionMessage"); jw.Write(monitoringAPICallAttempt.AWSExceptionMessage); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.SdkExceptionMessage)) { jw.WritePropertyName("SdkExceptionMessage"); jw.Write(monitoringAPICallAttempt.SdkExceptionMessage); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.SessionToken)) { jw.WritePropertyName("SessionToken"); jw.Write(monitoringAPICallAttempt.SessionToken); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.XAmzId2)) { jw.WritePropertyName("XAmzId2"); jw.Write(monitoringAPICallAttempt.XAmzId2); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.XAmznRequestId)) { jw.WritePropertyName("XAmznRequestId"); jw.Write(monitoringAPICallAttempt.XAmznRequestId); } if (!string.IsNullOrEmpty(monitoringAPICallAttempt.XAmzRequestId)) { jw.WritePropertyName("XAmzRequestId"); jw.Write(monitoringAPICallAttempt.XAmzRequestId); } if (monitoringAPICallAttempt.HttpStatusCode != null) { jw.WritePropertyName("HttpStatusCode"); jw.Write((int)monitoringAPICallAttempt.HttpStatusCode); } jw.WritePropertyName("AttemptLatency"); jw.Write(monitoringAPICallAttempt.AttemptLatency); jw.WriteObjectEnd(); response = jw.ToString(); return ASCIIEncoding.Unicode.GetByteCount(response) <= (8 * 1024); } /// /// Method to serialize MonitoringAPICallEvent CSM event to json. /// private static bool CreateUDPMessage(MonitoringAPICallEvent monitoringAPICallEvent, out string response) { JsonWriter jw = new JsonWriter(); jw.WriteObjectStart(); jw = CreateUDPMessage(monitoringAPICallEvent, jw); jw.WritePropertyName("Latency"); jw.Write(monitoringAPICallEvent.Latency); jw.WritePropertyName("AttemptCount"); jw.Write(monitoringAPICallEvent.AttemptCount); jw.WritePropertyName("MaxRetriesExceeded"); int maxRetriesValue = 0; if (monitoringAPICallEvent.IsLastExceptionRetryable) { maxRetriesValue = 1; } jw.Write(maxRetriesValue); if (monitoringAPICallEvent.FinalHttpStatusCode != null) { jw.WritePropertyName("FinalHttpStatusCode"); jw.Write((int)monitoringAPICallEvent.FinalHttpStatusCode); } if (!string.IsNullOrEmpty(monitoringAPICallEvent.FinalAWSException)) { jw.WritePropertyName("FinalAWSException"); jw.Write(monitoringAPICallEvent.FinalAWSException); } if (!string.IsNullOrEmpty(monitoringAPICallEvent.FinalSdkException)) { jw.WritePropertyName("FinalSdkException"); jw.Write(monitoringAPICallEvent.FinalSdkException); } if (!string.IsNullOrEmpty(monitoringAPICallEvent.FinalAWSExceptionMessage)) { jw.WritePropertyName("FinalAWSExceptionMessage"); jw.Write(monitoringAPICallEvent.FinalAWSExceptionMessage); } if (!string.IsNullOrEmpty(monitoringAPICallEvent.FinalSdkExceptionMessage)) { jw.WritePropertyName("FinalSdkExceptionMessage"); jw.Write(monitoringAPICallEvent.FinalSdkExceptionMessage); } jw.WriteObjectEnd(); response = jw.ToString(); return ASCIIEncoding.Unicode.GetByteCount(response) <= (8 * 1024); } /// /// Method to serialize MonitoringAPICall CSM event to json. /// private static JsonWriter CreateUDPMessage(MonitoringAPICall monitoringAPICall, JsonWriter jw) { string response = string.Empty; if (!string.IsNullOrEmpty(monitoringAPICall.Api)) { jw.WritePropertyName("Api"); jw.Write(monitoringAPICall.Api); } if (!string.IsNullOrEmpty(monitoringAPICall.Service)) { jw.WritePropertyName("Service"); jw.Write(monitoringAPICall.Service); } if (!string.IsNullOrEmpty(monitoringAPICall.ClientId)) { jw.WritePropertyName("ClientId"); jw.Write(monitoringAPICall.ClientId); } jw.WritePropertyName("Version"); jw.Write(monitoringAPICall.Version); if (!string.IsNullOrEmpty(monitoringAPICall.Type)) { jw.WritePropertyName("Type"); jw.Write(monitoringAPICall.Type); } jw.WritePropertyName("Timestamp"); jw.Write(monitoringAPICall.Timestamp); if (!string.IsNullOrEmpty(monitoringAPICall.Region)) { jw.WritePropertyName("Region"); jw.Write(monitoringAPICall.Region); } if (!string.IsNullOrEmpty(monitoringAPICall.UserAgent)) { jw.WritePropertyName("UserAgent"); jw.Write(monitoringAPICall.UserAgent); } return jw; } } }