refactor message processor, add api to rescan an hour of logs
This commit is contained in:
Родитель
3f643565a5
Коммит
d061817ada
|
@ -86,7 +86,7 @@ namespace nsgFunc
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkpoint.PutCheckpoint(checkpointTable, "", 0, blockList.Count()-1);
|
checkpoint.PutCheckpoint(checkpointTable, blockList.Count()-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,6 @@ namespace nsgFunc
|
||||||
{
|
{
|
||||||
public class Checkpoint : TableEntity
|
public class Checkpoint : TableEntity
|
||||||
{
|
{
|
||||||
|
|
||||||
public string LastBlockName { get; set; }
|
|
||||||
public long StartingByteOffset { get; set; }
|
|
||||||
public int CheckpointIndex { get; set; } // index of the last processed block list item
|
public int CheckpointIndex { get; set; } // index of the last processed block list item
|
||||||
|
|
||||||
public Checkpoint()
|
public Checkpoint()
|
||||||
|
@ -18,8 +15,6 @@ namespace nsgFunc
|
||||||
{
|
{
|
||||||
PartitionKey = partitionKey;
|
PartitionKey = partitionKey;
|
||||||
RowKey = rowKey;
|
RowKey = rowKey;
|
||||||
LastBlockName = blockName;
|
|
||||||
StartingByteOffset = offset;
|
|
||||||
CheckpointIndex = index;
|
CheckpointIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +37,8 @@ namespace nsgFunc
|
||||||
return checkpoint;
|
return checkpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PutCheckpoint(CloudTable checkpointTable, string lastBlockName, long startingByteOffset, int index)
|
public void PutCheckpoint(CloudTable checkpointTable, int index)
|
||||||
{
|
{
|
||||||
LastBlockName = lastBlockName;
|
|
||||||
StartingByteOffset = startingByteOffset;
|
|
||||||
CheckpointIndex = index;
|
CheckpointIndex = index;
|
||||||
|
|
||||||
TableOperation operation = TableOperation.InsertOrReplace(this);
|
TableOperation operation = TableOperation.InsertOrReplace(this);
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Azure.WebJobs;
|
||||||
|
using Microsoft.Azure.WebJobs.Extensions.Http;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Blob;
|
||||||
|
|
||||||
|
namespace nsgFunc
|
||||||
|
{
|
||||||
|
public static class RescanAPI
|
||||||
|
{
|
||||||
|
// https://<APP_NAME>.azurewebsites.net/api/rescan/2/17/8
|
||||||
|
//
|
||||||
|
[FunctionName("RescanAPI")]
|
||||||
|
public static async Task<IActionResult> Run(
|
||||||
|
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "rescan/resourceId=/SUBSCRIPTIONS/{subId}/RESOURCEGROUPS/{resourceGroup}/PROVIDERS/MICROSOFT.NETWORK/NETWORKSECURITYGROUPS/{nsgName}/y={blobYear}/m={blobMonth}/d={blobDay}/h={blobHour}/m={blobMinute}/macAddress={mac}/PT1H.json")]
|
||||||
|
// [Table("checkpoints", Connection = "AzureWebJobsStorage")] CloudTable checkpointToReset,
|
||||||
|
HttpRequest req,
|
||||||
|
Binder checkpointsBinder,
|
||||||
|
Binder nsgDataBlobBinder,
|
||||||
|
string subId, string resourceGroup, string nsgName, string blobYear, string blobMonth, string blobDay, string blobHour, string blobMinute, string mac,
|
||||||
|
ILogger log)
|
||||||
|
{
|
||||||
|
string nsgSourceDataAccount = Util.GetEnvironmentVariable("nsgSourceDataAccount");
|
||||||
|
if (nsgSourceDataAccount.Length == 0)
|
||||||
|
{
|
||||||
|
log.LogError("Value for nsgSourceDataAccount is required.");
|
||||||
|
throw new System.ArgumentNullException("nsgSourceDataAccount", "Please provide setting.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string AzureWebJobsStorage = Util.GetEnvironmentVariable("AzureWebJobsStorage");
|
||||||
|
if (AzureWebJobsStorage.Length == 0)
|
||||||
|
{
|
||||||
|
log.LogError("Value for AzureWebJobsStorage is required.");
|
||||||
|
throw new System.ArgumentNullException("AzureWebJobsStorage", "Please provide setting.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string blobContainerName = Util.GetEnvironmentVariable("blobContainerName");
|
||||||
|
if (blobContainerName.Length == 0)
|
||||||
|
{
|
||||||
|
log.LogError("Value for blobContainerName is required.");
|
||||||
|
throw new System.ArgumentNullException("blobContainerName", "Please provide setting.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var blobName = $"resourceId=/SUBSCRIPTIONS/{subId}/RESOURCEGROUPS/{resourceGroup}/PROVIDERS/MICROSOFT.NETWORK/NETWORKSECURITYGROUPS/{nsgName}/y={blobYear}/m={blobMonth}/d={blobDay}/h={blobHour}/m={blobMinute}/macAddress={mac}/PT1H.json";
|
||||||
|
var blobDetails = new BlobDetails(subId, resourceGroup, nsgName, blobYear, blobMonth, blobDay, blobHour, blobMinute, mac);
|
||||||
|
|
||||||
|
var tableAttributes = new Attribute[]
|
||||||
|
{
|
||||||
|
new TableAttribute("checkpoints"),
|
||||||
|
new StorageAccountAttribute("AzureWebJobsStorage")
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CloudTable CheckpointTable = await checkpointsBinder.BindAsync<CloudTable>(tableAttributes);
|
||||||
|
TableOperation getOperation = TableOperation.Retrieve<Checkpoint>(blobDetails.GetPartitionKey(), blobDetails.GetRowKey());
|
||||||
|
TableResult result = await CheckpointTable.ExecuteAsync(getOperation);
|
||||||
|
Checkpoint c = (Checkpoint)result.Result;
|
||||||
|
c.CheckpointIndex = 1;
|
||||||
|
TableOperation putOperation = TableOperation.InsertOrReplace(c);
|
||||||
|
await CheckpointTable.ExecuteAsync(putOperation);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.LogError(string.Format("Error binding checkpoints table: {0}", ex.Message));
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
var attributes = new Attribute[]
|
||||||
|
{
|
||||||
|
new BlobAttribute(string.Format("{0}/{1}", blobContainerName, blobName)),
|
||||||
|
new StorageAccountAttribute(nsgSourceDataAccount)
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CloudBlockBlob blob = await nsgDataBlobBinder.BindAsync<CloudBlockBlob>(attributes);
|
||||||
|
await blob.FetchAttributesAsync();
|
||||||
|
var metadata = blob.Metadata;
|
||||||
|
if (metadata.ContainsKey("rescan"))
|
||||||
|
{
|
||||||
|
int numberRescans = Convert.ToInt32(metadata["rescan"]);
|
||||||
|
metadata["rescan"] = (numberRescans + 1).ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metadata.Add("rescan", "1");
|
||||||
|
}
|
||||||
|
await blob.SetMetadataAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.LogError(string.Format("Error binding blob input: {0}", ex.Message));
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ActionResult)new OkObjectResult($"NSG flow logs for {blobName} were requested.");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,9 @@ using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
class ObjectDenormalizer
|
class DenormalizedRecord
|
||||||
{
|
{
|
||||||
public string time { get; set; }
|
public string time { get; set; }
|
||||||
public string category { get; set; }
|
public string category { get; set; }
|
||||||
|
@ -28,7 +29,7 @@ class ObjectDenormalizer
|
||||||
public string packetsDtoS { get; set; }
|
public string packetsDtoS { get; set; }
|
||||||
public string bytesDtoS { get; set; }
|
public string bytesDtoS { get; set; }
|
||||||
|
|
||||||
public ObjectDenormalizer(
|
public DenormalizedRecord(
|
||||||
float version,
|
float version,
|
||||||
string time,
|
string time,
|
||||||
string category,
|
string category,
|
||||||
|
@ -71,6 +72,39 @@ class ObjectDenormalizer
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int SizeOfObject()
|
||||||
|
{
|
||||||
|
int objectSize = 0;
|
||||||
|
|
||||||
|
objectSize += this.version.ToString().Length + 7 + 6;
|
||||||
|
objectSize += this.time.Length + 4 + 6;
|
||||||
|
objectSize += this.category.Length + 8 + 6;
|
||||||
|
objectSize += this.operationName.Length + 13 + 6;
|
||||||
|
objectSize += this.resourceId.Length + 10 + 6;
|
||||||
|
objectSize += this.nsgRuleName.Length + 11 + 6;
|
||||||
|
objectSize += this.mac.Length + 3 + 6;
|
||||||
|
objectSize += this.startTime.Length + 9 + 6;
|
||||||
|
objectSize += this.sourceAddress.Length + 13 + 6;
|
||||||
|
objectSize += this.destinationAddress.Length + 18 + 6;
|
||||||
|
objectSize += this.sourcePort.Length + 10 + 6;
|
||||||
|
objectSize += this.destinationPort.Length + 15 + 6;
|
||||||
|
objectSize += this.deviceDirection.Length + 15 + 6;
|
||||||
|
objectSize += this.deviceAction.Length + 12 + 6;
|
||||||
|
if (this.version >= 2.0)
|
||||||
|
{
|
||||||
|
objectSize += this.flowState.Length + 9 + 6;
|
||||||
|
objectSize += this.packetsDtoS == null ? 0 : this.packetsDtoS.Length + 11 + 6;
|
||||||
|
objectSize += this.packetsStoD == null ? 0 : this.packetsStoD.Length + 11 + 6;
|
||||||
|
objectSize += this.bytesDtoS == null ? 0 : this.bytesDtoS.Length + 9 + 6;
|
||||||
|
objectSize += this.bytesStoD == null ? 0 : this.bytesStoD.Length + 9 + 6;
|
||||||
|
}
|
||||||
|
return objectSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OutgoingRecords
|
||||||
|
{
|
||||||
|
public List<DenormalizedRecord> records { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class NSGFlowLogTuple
|
class NSGFlowLogTuple
|
||||||
|
|
|
@ -5,23 +5,20 @@ using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace nsgFunc
|
namespace nsgFunc
|
||||||
{
|
{
|
||||||
public partial class Util
|
public partial class Util
|
||||||
{
|
{
|
||||||
const int MAXTRANSMISSIONSIZE = 255 * 1024;
|
const int MAXTRANSMISSIONSIZE = 512 * 1024;
|
||||||
// const int MAXTRANSMISSIONSIZE = 2 * 1024;
|
//const int MAXTRANSMISSIONSIZE = 2 * 1024;
|
||||||
|
|
||||||
public static async Task obEventHub(string newClientContent, ILogger log)
|
private static Lazy<EventHubClient> LazyEventHubConnection = new Lazy<EventHubClient>(() =>
|
||||||
{
|
{
|
||||||
string EventHubConnectionString = GetEnvironmentVariable("eventHubConnection");
|
string EventHubConnectionString = GetEnvironmentVariable("eventHubConnection");
|
||||||
string EventHubName = GetEnvironmentVariable("eventHubName");
|
string EventHubName = GetEnvironmentVariable("eventHubName");
|
||||||
if (EventHubConnectionString.Length == 0 || EventHubName.Length == 0)
|
|
||||||
{
|
|
||||||
log.LogError("Values for eventHubConnection and eventHubName are required.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var connectionStringBuilder = new EventHubsConnectionStringBuilder(EventHubConnectionString)
|
var connectionStringBuilder = new EventHubsConnectionStringBuilder(EventHubConnectionString)
|
||||||
{
|
{
|
||||||
|
@ -29,16 +26,22 @@ namespace nsgFunc
|
||||||
};
|
};
|
||||||
var eventHubClient = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString());
|
var eventHubClient = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString());
|
||||||
|
|
||||||
foreach (var bundleOfMessages in bundleMessages(newClientContent, log))
|
return eventHubClient;
|
||||||
{
|
});
|
||||||
//log.Info(String.Format("-----Outgoing message is: {0}", bundleOfMessages));
|
|
||||||
|
|
||||||
|
public static async Task obEventHub(string newClientContent, ILogger log)
|
||||||
|
{
|
||||||
|
var eventHubClient = LazyEventHubConnection.Value;
|
||||||
|
|
||||||
|
foreach (var bundleOfMessages in bundleMessageListsJson(newClientContent, log))
|
||||||
|
{
|
||||||
await eventHubClient.SendAsync(new EventData(Encoding.UTF8.GetBytes(bundleOfMessages)));
|
await eventHubClient.SendAsync(new EventData(Encoding.UTF8.GetBytes(bundleOfMessages)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.Generic.IEnumerable<string> bundleMessages(string newClientContent, ILogger log)
|
static System.Collections.Generic.IEnumerable<string> bundleMessages(string newClientContent, ILogger log)
|
||||||
{
|
{
|
||||||
|
var numberOfItemsInBundle = 0;
|
||||||
var transmission = new StringBuilder(MAXTRANSMISSIONSIZE);
|
var transmission = new StringBuilder(MAXTRANSMISSIONSIZE);
|
||||||
transmission.Append("{\"records\":[");
|
transmission.Append("{\"records\":[");
|
||||||
bool firstRecord = true;
|
bool firstRecord = true;
|
||||||
|
@ -69,6 +72,8 @@ namespace nsgFunc
|
||||||
if (transmission.Length + message.Length > MAXTRANSMISSIONSIZE)
|
if (transmission.Length + message.Length > MAXTRANSMISSIONSIZE)
|
||||||
{
|
{
|
||||||
transmission.Append("]}");
|
transmission.Append("]}");
|
||||||
|
log.LogInformation("Number of items in bundle: {0}", numberOfItemsInBundle);
|
||||||
|
numberOfItemsInBundle = 0;
|
||||||
yield return transmission.ToString();
|
yield return transmission.ToString();
|
||||||
transmission.Clear();
|
transmission.Clear();
|
||||||
transmission.Append("{\"records\":[");
|
transmission.Append("{\"records\":[");
|
||||||
|
@ -86,6 +91,7 @@ namespace nsgFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
transmission.Append(message);
|
transmission.Append(message);
|
||||||
|
numberOfItemsInBundle++;
|
||||||
}
|
}
|
||||||
if (transmission.Length > 0)
|
if (transmission.Length > 0)
|
||||||
{
|
{
|
||||||
|
@ -94,6 +100,96 @@ namespace nsgFunc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static System.Collections.Generic.IEnumerable<string> bundleMessageLists(string newClientContent, ILogger log)
|
||||||
|
{
|
||||||
|
var transmission = new StringBuilder(MAXTRANSMISSIONSIZE);
|
||||||
|
foreach (var messageList in denormalizeLists(newClientContent, null, log))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// messageList looks like this: (List<xxx>)
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "time": "xxx",
|
||||||
|
// "category": "xxx",
|
||||||
|
// "operationName": "xxx",
|
||||||
|
// "version": "xxx",
|
||||||
|
// "deviceExtId": "xxx",
|
||||||
|
// "flowOrder": "xxx",
|
||||||
|
// "nsgRuleName": "xxx",
|
||||||
|
// "dmac|smac": "xxx",
|
||||||
|
// "rt": "xxx",
|
||||||
|
// "src": "xxx",
|
||||||
|
// "dst": "xxx",
|
||||||
|
// "spt": "xxx",
|
||||||
|
// "dpt": "xxx",
|
||||||
|
// "proto": "xxx",
|
||||||
|
// "deviceDirection": "xxx",
|
||||||
|
// "act": "xxx"
|
||||||
|
// }
|
||||||
|
transmission.Append("{\"records\":[");
|
||||||
|
var numberOfItemsInBundle = 0;
|
||||||
|
bool firstRecord = true;
|
||||||
|
|
||||||
|
foreach (var message in messageList)
|
||||||
|
{
|
||||||
|
if (firstRecord)
|
||||||
|
{
|
||||||
|
firstRecord = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transmission.Append(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
transmission.Append(message);
|
||||||
|
numberOfItemsInBundle++;
|
||||||
|
}
|
||||||
|
transmission.Append("]}");
|
||||||
|
log.LogInformation("Number of items in bundle: {0}", numberOfItemsInBundle);
|
||||||
|
numberOfItemsInBundle = 0;
|
||||||
|
yield return transmission.ToString();
|
||||||
|
transmission.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static System.Collections.Generic.IEnumerable<string> bundleMessageListsJson(string newClientContent, ILogger log)
|
||||||
|
{
|
||||||
|
foreach (var messageList in denormalizedRecords(newClientContent, null, log))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// messageList looks like this: (List<xxx>)
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "time": "xxx",
|
||||||
|
// "category": "xxx",
|
||||||
|
// "operationName": "xxx",
|
||||||
|
// "version": "xxx",
|
||||||
|
// "deviceExtId": "xxx",
|
||||||
|
// "flowOrder": "xxx",
|
||||||
|
// "nsgRuleName": "xxx",
|
||||||
|
// "dmac|smac": "xxx",
|
||||||
|
// "rt": "xxx",
|
||||||
|
// "src": "xxx",
|
||||||
|
// "dst": "xxx",
|
||||||
|
// "spt": "xxx",
|
||||||
|
// "dpt": "xxx",
|
||||||
|
// "proto": "xxx",
|
||||||
|
// "deviceDirection": "xxx",
|
||||||
|
// "act": "xxx"
|
||||||
|
// }
|
||||||
|
|
||||||
|
var outgoingRecords = new OutgoingRecords();
|
||||||
|
outgoingRecords.records = messageList;
|
||||||
|
|
||||||
|
var outgoingJson = JsonConvert.SerializeObject(outgoingRecords, new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
NullValueHandling = NullValueHandling.Ignore
|
||||||
|
});
|
||||||
|
|
||||||
|
yield return outgoingJson;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static System.Collections.Generic.IEnumerable<string> denormalizeRecords(string newClientContent, Binder errorRecordBinder, ILogger log)
|
static System.Collections.Generic.IEnumerable<string> denormalizeRecords(string newClientContent, Binder errorRecordBinder, ILogger log)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -132,7 +228,7 @@ namespace nsgFunc
|
||||||
{
|
{
|
||||||
var tuple = new NSGFlowLogTuple(flowTuple, version);
|
var tuple = new NSGFlowLogTuple(flowTuple, version);
|
||||||
|
|
||||||
var denormalizedObject = new ObjectDenormalizer(
|
var denormalizedObject = new DenormalizedRecord(
|
||||||
record.properties.Version,
|
record.properties.Version,
|
||||||
record.time,
|
record.time,
|
||||||
record.category,
|
record.category,
|
||||||
|
@ -148,6 +244,151 @@ namespace nsgFunc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
static System.Collections.Generic.IEnumerable<List<string>> denormalizeLists(string newClientContent, Binder errorRecordBinder, ILogger log)
|
||||||
|
{
|
||||||
|
var outgoingList = new List<string>(450);
|
||||||
|
var sizeOfListItems = 0;
|
||||||
|
NSGFlowLogRecords logs = JsonConvert.DeserializeObject<NSGFlowLogRecords>(newClientContent);
|
||||||
|
|
||||||
|
foreach (var record in logs.records)
|
||||||
|
{
|
||||||
|
float version = record.properties.Version;
|
||||||
|
|
||||||
|
foreach (var outerFlow in record.properties.flows)
|
||||||
|
{
|
||||||
|
foreach (var innerFlow in outerFlow.flows)
|
||||||
|
{
|
||||||
|
foreach (var flowTuple in innerFlow.flowTuples)
|
||||||
|
{
|
||||||
|
var tuple = new NSGFlowLogTuple(flowTuple, version);
|
||||||
|
|
||||||
|
var denormalizedObject = new DenormalizedRecord(
|
||||||
|
record.properties.Version,
|
||||||
|
record.time,
|
||||||
|
record.category,
|
||||||
|
record.operationName,
|
||||||
|
record.resourceId,
|
||||||
|
outerFlow.rule,
|
||||||
|
innerFlow.mac,
|
||||||
|
tuple);
|
||||||
|
string outgoingJson = denormalizedObject.ToString();
|
||||||
|
|
||||||
|
if (sizeOfListItems + outgoingJson.Length > MAXTRANSMISSIONSIZE+20)
|
||||||
|
{
|
||||||
|
yield return outgoingList;
|
||||||
|
outgoingList.Clear();
|
||||||
|
sizeOfListItems = 0;
|
||||||
|
}
|
||||||
|
outgoingList.Add(outgoingJson);
|
||||||
|
sizeOfListItems += outgoingJson.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outgoingList.Count > 0)
|
||||||
|
{
|
||||||
|
yield return outgoingList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerable<DenormalizedRecord[]> denormalizeArrays(string newClientContent, Binder errorRecordBinder, ILogger log)
|
||||||
|
{
|
||||||
|
var outgoingArray = Array.CreateInstance(typeof(DenormalizedRecord), 450);
|
||||||
|
var sizeOfArrayItems = 0;
|
||||||
|
var arrayItemIndex = 0;
|
||||||
|
NSGFlowLogRecords logs = JsonConvert.DeserializeObject<NSGFlowLogRecords>(newClientContent);
|
||||||
|
|
||||||
|
foreach (var record in logs.records)
|
||||||
|
{
|
||||||
|
float version = record.properties.Version;
|
||||||
|
|
||||||
|
foreach (var outerFlow in record.properties.flows)
|
||||||
|
{
|
||||||
|
foreach (var innerFlow in outerFlow.flows)
|
||||||
|
{
|
||||||
|
foreach (var flowTuple in innerFlow.flowTuples)
|
||||||
|
{
|
||||||
|
var tuple = new NSGFlowLogTuple(flowTuple, version);
|
||||||
|
|
||||||
|
var denormalizedObject = new DenormalizedRecord(
|
||||||
|
record.properties.Version,
|
||||||
|
record.time,
|
||||||
|
record.category,
|
||||||
|
record.operationName,
|
||||||
|
record.resourceId,
|
||||||
|
outerFlow.rule,
|
||||||
|
innerFlow.mac,
|
||||||
|
tuple);
|
||||||
|
string outgoingJson = denormalizedObject.ToString();
|
||||||
|
|
||||||
|
if (sizeOfArrayItems + outgoingJson.Length > MAXTRANSMISSIONSIZE + 20)
|
||||||
|
{
|
||||||
|
yield return (DenormalizedRecord[])outgoingArray;
|
||||||
|
Array.Clear(outgoingArray, 0, 450);
|
||||||
|
sizeOfArrayItems = 0;
|
||||||
|
arrayItemIndex = 0;
|
||||||
|
}
|
||||||
|
outgoingArray.SetValue(denormalizedObject, arrayItemIndex++);
|
||||||
|
sizeOfArrayItems += outgoingJson.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arrayItemIndex > 0)
|
||||||
|
{
|
||||||
|
yield return (DenormalizedRecord[])outgoingArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerable<List<DenormalizedRecord>> denormalizedRecords(string newClientContent, Binder errorRecordBinder, ILogger log)
|
||||||
|
{
|
||||||
|
var outgoingList = new List<DenormalizedRecord>(450);
|
||||||
|
var sizeOfListItems = 0;
|
||||||
|
|
||||||
|
NSGFlowLogRecords logs = JsonConvert.DeserializeObject<NSGFlowLogRecords>(newClientContent);
|
||||||
|
|
||||||
|
foreach (var record in logs.records)
|
||||||
|
{
|
||||||
|
float version = record.properties.Version;
|
||||||
|
|
||||||
|
foreach (var outerFlow in record.properties.flows)
|
||||||
|
{
|
||||||
|
foreach (var innerFlow in outerFlow.flows)
|
||||||
|
{
|
||||||
|
foreach (var flowTuple in innerFlow.flowTuples)
|
||||||
|
{
|
||||||
|
var tuple = new NSGFlowLogTuple(flowTuple, version);
|
||||||
|
|
||||||
|
var denormalizedRecord = new DenormalizedRecord(
|
||||||
|
record.properties.Version,
|
||||||
|
record.time,
|
||||||
|
record.category,
|
||||||
|
record.operationName,
|
||||||
|
record.resourceId,
|
||||||
|
outerFlow.rule,
|
||||||
|
innerFlow.mac,
|
||||||
|
tuple);
|
||||||
|
|
||||||
|
var sizeOfDenormalizedRecord = denormalizedRecord.SizeOfObject();
|
||||||
|
|
||||||
|
if (sizeOfListItems + sizeOfDenormalizedRecord > MAXTRANSMISSIONSIZE + 20)
|
||||||
|
{
|
||||||
|
yield return outgoingList;
|
||||||
|
outgoingList.Clear();
|
||||||
|
sizeOfListItems = 0;
|
||||||
|
}
|
||||||
|
outgoingList.Add(denormalizedRecord);
|
||||||
|
sizeOfListItems += sizeOfDenormalizedRecord;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sizeOfListItems > 0)
|
||||||
|
{
|
||||||
|
yield return outgoingList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче