/// <summary> /// Perform event to message Json encoding /// </summary> /// <param name="messages"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsJson( IEnumerable <DataSetMessageModel> messages) { var notifications = GetMonitoredItemMessages(messages, MessageEncoding.Json); if (notifications.Count() == 0) { yield break; } var encodingContext = messages.First().ServiceMessageContext; foreach (var networkMessage in notifications) { var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; networkMessage.Encode(encoder); encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaLegacyPublisher, MessageSchema = MessageSchemaTypes.MonitoredItemMessageJson }; yield return(encoded); } }
/// <summary> /// Perform json encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Json, encodingContext); if (!notifications.Any()) { yield break; } var routingInfo = messages.FirstOrDefault(m => m?.WriterGroup != null)?.WriterGroup.WriterGroupId; foreach (var networkMessage in notifications) { int notificationsPerMessage = networkMessage.Messages.Sum(m => m.Payload.Count); var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; networkMessage.Encode(encoder); encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Json, MessageSchema = MessageSchemaTypes.NetworkMessageJson, RoutingInfo = _enableRoutingInfo ? routingInfo : null, }; if (encoded.Body.Length > maxMessageSize) { // Message too large, drop it. NotificationsDroppedCount += (uint)notificationsPerMessage; _logger.Warning("Message too large, dropped {notificationsPerMessage} values", notificationsPerMessage); continue; } NotificationsProcessedCount += (uint)notificationsPerMessage; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; yield return(encoded); } }
/// <summary> /// Perform json encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Json, encodingContext); if (notifications.Count() == 0) { yield break; } foreach (var networkMessage in notifications) { ulong notificationsPerMessage = (ulong)networkMessage.Messages.Sum(m => m.Payload.Count); var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; networkMessage.Encode(encoder); encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Json, MessageSchema = MessageSchemaTypes.NetworkMessageJson }; if (encoded.Body.Length > maxMessageSize) { // this message is too large to be processed. Drop it // TODO Trace NotificationsDroppedCount++; yield break; } NotificationsProcessedCount++; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; yield return(encoded); } }
/// <summary> /// DataSetMessage to NetworkMessage Json batched encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { var notifications = GetNetworkMessages(messages, MessageEncoding.Json); if (notifications.Count() == 0) { yield break; } // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.First().ServiceMessageContext; var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 2; // array brackets maxMessageSize -= 2048; // reserve 2k for header var chunk = new Collection <NetworkMessage>(); while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperWriter = new StringWriter(); var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; notification.Encode(helperEncoder); helperEncoder.Close(); var notificationSize = Encoding.UTF8.GetByteCount(helperWriter.ToString()); if (notificationSize > maxMessageSize) { // we cannot handle this notification. Drop it. // TODO Trace NotificationsDroppedCount++; processing = current.MoveNext(); } else { messageCompleted = maxMessageSize < (messageSize + notificationSize); if (!messageCompleted) { NotificationsProcessedCount++; chunk.Add(notification); processing = current.MoveNext(); messageSize += notificationSize + (processing ? 1 : 0); } } } if (!processing || messageCompleted) { var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext, JsonEncoderEx.JsonEncoding.Array) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; foreach (var element in chunk) { encoder.WriteEncodeable(null, element); } encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaJson, MessageSchema = MessageSchemaTypes.NetworkMessageJson }; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + chunk.Count) / (MessagesProcessedCount + 1); MessagesProcessedCount++; chunk.Clear(); messageSize = 2; yield return(encoded); } } }
/// <summary> /// Perform DataSetMessageModel to NetworkMessageModel batch using Json encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { var notifications = GetMonitoredItemMessages(messages, MessageEncoding.Json); if (notifications.Count() == 0) { yield break; } var encodingContext = messages.First().ServiceMessageContext; var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 2; // array brackets maxMessageSize -= 2048; // reserve 2k for header var chunk = new Collection <MonitoredItemMessage>(); while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperWriter = new StringWriter(); var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; notification.Encode(helperEncoder); helperEncoder.Close(); var notificationSize = Encoding.UTF8.GetByteCount(helperWriter.ToString()); messageCompleted = maxMessageSize < (messageSize + notificationSize); if (!messageCompleted) { chunk.Add(notification); processing = current.MoveNext(); messageSize += notificationSize + (processing ? 1 : 0); } } if (!processing || messageCompleted) { var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext, JsonEncoderEx.JsonEncoding.Array) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; foreach (var element in chunk) { encoder.WriteEncodeable(null, element); } encoder.Close(); chunk.Clear(); messageSize = 2; // array brackets var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaJson, MessageSchema = MessageSchemaTypes.MonitoredItemMessageJson }; yield return(encoded); } } }
/// <summary> /// DataSetMessage to NetworkMessage Json batched encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Json, encodingContext); if (!notifications.Any()) { yield break; } var routingInfo = messages.FirstOrDefault(m => m?.WriterGroup != null)?.WriterGroup.WriterGroupId; var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 2; // array brackets var chunk = new Collection <NetworkMessage>(); int notificationsPerMessage = 0; while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperWriter = new StringWriter(); var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; notification.Encode(helperEncoder); helperEncoder.Close(); var notificationSize = Encoding.UTF8.GetByteCount(helperWriter.ToString()); var notificationsInBatch = notification.Messages.Sum(m => m.Payload.Count); if (notificationSize > maxMessageSize) { // Message too large, drop it. NotificationsDroppedCount += (uint)notificationsInBatch; _logger.Warning("Message too large, dropped {notificationsInBatch} values", notificationsInBatch); processing = current.MoveNext(); } else { messageCompleted = maxMessageSize < (messageSize + notificationSize); if (!messageCompleted) { chunk.Add(notification); NotificationsProcessedCount += (uint)notificationsInBatch; notificationsPerMessage += notificationsInBatch; processing = current.MoveNext(); messageSize += notificationSize + (processing ? 1 : 0); } } } if (messageCompleted || (!processing && chunk.Count > 0)) { var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext, JsonEncoderEx.JsonEncoding.Array) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; foreach (var element in chunk) { encoder.WriteEncodeable(null, element); } encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Json, MessageSchema = MessageSchemaTypes.NetworkMessageJson, RoutingInfo = _enableRoutingInfo ? routingInfo : null, }; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; chunk.Clear(); messageSize = 2; notificationsPerMessage = 0; yield return(encoded); } } }