Add custom metrics to defender demo (#507)

Adds custom metrics to the defender demo. The metrics added are a list of the task ids and the stack high water mark.
pull/525/head
Archit Gupta 4 years ago committed by GitHub
parent e61730c9b1
commit c8fa483b68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -35,18 +35,20 @@
* with another MQTT library. This demo requires using the AWS IoT broker as
* Device Defender is an AWS service.
*
* This demo connects to the AWS IoT broker and subscribes to the device
* defender topics. It then collects metrics for the open ports and sockets on
* the device using FreeRTOS+TCP, and generates a device defender report. The
* This demo subscribes to the device defender topics. It then collects metrics
* for the open ports and sockets on the device using FreeRTOS+TCP. Additonally
* the stack high water mark and task IDs are collected for custom metrics.
* These metrics are used to generate a device defender report. The
* report is then published, and the demo waits for a response from the device
* defender service. Upon receiving the response or timing out, the demo
* finishes.
* defender service. Upon receiving an accepted response, the demo finishes.
* If the demo receives a rejected response or times out, the demo repeats up to
* a maximum of DEFENDER_MAX_DEMO_LOOP_COUNT times.
*
* This demo sets the report ID to xTaskGetTickCount(), which may collide if
* the device is reset. Reports for a Thing with a previously used report ID
* will be assumed to be duplicates and discarded by the Device Defender
* service. The report ID needs to be unique per report sent with a given
* Thing. We recommend using an increasing unique id such as the current
* Thing. We recommend using an increasing unique ID such as the current
* timestamp.
*/
@ -97,7 +99,7 @@
#define DEFENDER_RESPONSE_WAIT_SECONDS ( 2 )
/**
* @brief Name of the report id field in the response from the AWS IoT Device
* @brief Name of the report ID field in the response from the AWS IoT Device
* Defender service.
*/
#define DEFENDER_RESPONSE_REPORT_ID_FIELD "reportId"
@ -133,8 +135,8 @@ typedef enum
ReportStatusRejected
} ReportStatus_t;
/**
* @brief Each compilation unit that consumes the NetworkContext must define it.
/**
* @brief Each compilation unit that consumes the NetworkContext must define it.
* It should contain a single pointer to the type of your desired transport.
* When using multiple transports in the same compilation unit, define this pointer as void *.
*
@ -195,6 +197,16 @@ static uint16_t pusOpenUdpPorts[ democonfigOPEN_UDP_PORTS_ARRAY_SIZE ];
*/
static Connection_t pxEstablishedConnections[ democonfigESTABLISHED_CONNECTIONS_ARRAY_SIZE ];
/**
* @brief Array of task statuses, used to generate custom metrics.
*/
static TaskStatus_t pxTaskStatusList[ democonfigCUSTOM_METRICS_TASKS_ARRAY_SIZE ];
/**
* @brief Task numbers custom metric array.
*/
static uint32_t pulCustomMetricsTaskNumbers[ democonfigCUSTOM_METRICS_TASKS_ARRAY_SIZE ];
/**
* @brief All the metrics sent in the device defender report.
*/
@ -211,9 +223,10 @@ static ReportStatus_t xReportStatus;
static char pcDeviceMetricsJsonReport[ democonfigDEVICE_METRICS_REPORT_BUFFER_SIZE ];
/**
* @brief Report Id sent in the defender report.
* @brief Report ID sent in the defender report.
*/
static uint32_t ulReportId = 0UL;
/*-----------------------------------------------------------*/
/**
@ -463,7 +476,9 @@ static bool prvCollectDeviceMetrics( void )
{
bool xStatus = false;
eMetricsCollectorStatus eMetricsCollectorStatus;
uint32_t ulNumOpenTcpPorts = 0UL, ulNumOpenUdpPorts = 0UL, ulNumEstablishedConnections = 0UL;
uint32_t ulNumOpenTcpPorts = 0UL, ulNumOpenUdpPorts = 0UL, ulNumEstablishedConnections = 0UL, i;
UBaseType_t uxTasksWritten = { 0 };
TaskStatus_t pxTaskStatus = { 0 };
/* Collect bytes and packets sent and received. */
eMetricsCollectorStatus = eGetNetworkStats( &( xNetworkStats ) );
@ -516,6 +531,36 @@ static bool prvCollectDeviceMetrics( void )
}
}
/* Collect custom metrics. This demo sends this task's stack high water mark
* as a number type custom metric and the current task IDs as a list of
* numbers type custom metric. */
if( eMetricsCollectorStatus == eMetricsCollectorSuccess )
{
vTaskGetInfo(
/* Query this task. */
NULL,
&pxTaskStatus,
/* Include the stack high water mark value. */
pdTRUE,
/* Don't include the task state in the TaskStatus_t structure. */
0 );
uxTasksWritten = uxTaskGetSystemState( pxTaskStatusList, democonfigCUSTOM_METRICS_TASKS_ARRAY_SIZE, NULL );
if( uxTasksWritten == 0 )
{
eMetricsCollectorStatus = eMetricsCollectorCollectionFailed;
LogError( ( "Failed to collect system state. uxTaskGetSystemState() failed due to insufficient buffer space.",
eMetricsCollectorStatus ) );
}
else
{
for( i = 0; i < uxTasksWritten; i++ )
{
pulCustomMetricsTaskNumbers[ i ] = pxTaskStatusList[ i ].xTaskNumber;
}
}
}
/* Populate device metrics. */
if( eMetricsCollectorStatus == eMetricsCollectorSuccess )
{
@ -527,6 +572,9 @@ static bool prvCollectDeviceMetrics( void )
xDeviceMetrics.ulOpenUdpPortsArrayLength = ulNumOpenUdpPorts;
xDeviceMetrics.pxEstablishedConnectionsArray = &( pxEstablishedConnections[ 0 ] );
xDeviceMetrics.ulEstablishedConnectionsArrayLength = ulNumEstablishedConnections;
xDeviceMetrics.ulStackHighWaterMark = pxTaskStatus.usStackHighWaterMark;
xDeviceMetrics.pulTaskIdArray = pulCustomMetricsTaskNumbers;
xDeviceMetrics.ulTaskIdArrayLength = uxTasksWritten;
}
return xStatus;
@ -671,14 +719,14 @@ void prvDefenderDemoTask( void * pvParameters )
* DEFENDER_MAX_DEMO_LOOP_COUNT times. */
do
{
/* Set a report Id to be used.
/* Set a report ID to be used.
*
* !!!NOTE!!!
* This demo sets the report ID to xTaskGetTickCount(), which may collide
* if the device is reset. Reports for a Thing with a previously used
* report ID will be assumed to be duplicates and discarded by the Device
* Defender service. The report ID needs to be unique per report sent with
* a given Thing. We recommend using an increasing unique id such as the
* a given Thing. We recommend using an increasing unique ID such as the
* current timestamp. */
ulReportId = ( uint32_t ) xTaskGetTickCount();

@ -48,7 +48,8 @@
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 60 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the Win32 thread. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 2048U * 1024U ) )
#define configMAX_TASK_NAME_LEN ( 15 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_CO_ROUTINES 0
@ -103,15 +104,6 @@
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_pcTaskGetTaskName 1
/* This demo makes use of one or more example stats formatting functions. These
* format the raw data provided by the uxTaskGetSystemState() function in to human
* readable ASCII form. See the notes in the implementation of vTaskList() within
* FreeRTOS/Source/tasks.c for limitations. configUSE_STATS_FORMATTING_FUNCTIONS
* is set to 2 so the formatting functions are included without the stdio.h being
* included in tasks.c. That is because this project defines its own sprintf()
* functions. */
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
/* Assert call defined for debug builds. */
#ifdef _DEBUG
extern void vAssertCalled( const char * pcFile,

@ -52,4 +52,44 @@
/************ End of logging configuration ****************/
/**
* AWS IoT Device Defender Service supports both long and short names for keys
* in the report sent by a device. For example,
*
* A device defender report using long key names:
* {
* "header": {
* "report_id": 1530304554,
* "version": "1.0"
* },
* "metrics": {
* "network_stats": {
* "bytes_in": 29358693495,
* "bytes_out": 26485035,
* "packets_in": 10013573555,
* "packets_out": 11382615
* }
* }
* }
*
* An equivalent report using short key names:
* {
* "hed": {
* "rid": 1530304554,
* "v": "1.0"
* },
* "met": {
* "ns": {
* "bi": 29358693495,
* "bo": 26485035,
* "pi": 10013573555,
* "po": 11382615
* }
* }
* }
*
* Set to 1 to enable use of long key names in the defender report.
*/
#define DEFENDER_USE_LONG_KEYS 0
#endif /* ifndef DEFENDER_CONFIG_H_ */

@ -261,6 +261,13 @@ extern void vLoggingPrintf( const char * pcFormatString,
*/
#define democonfigESTABLISHED_CONNECTIONS_ARRAY_SIZE 10
/**
* @brief Size of the task numbers array.
*
* This must be at least the number of tasks used.
*/
#define democonfigCUSTOM_METRICS_TASKS_ARRAY_SIZE 10
/**
* @brief Size of the buffer which contains the generated device defender report.
*

@ -43,9 +43,6 @@
#include "FreeRTOS.h"
#include "FreeRTOS_IP.h"
/* FreeRTOS+TCP tcp_netstat utility include. */
#include "tcp_netstat.h"
/* Demo config. */
#include "demo_config.h"

@ -36,6 +36,9 @@
/* Demo config. */
#include "demo_config.h"
/* Device Defender Client Library. */
#include "defender.h"
/* Interface include. */
#include "report_builder.h"
@ -50,53 +53,68 @@
/* Formats used to generate the JSON report. */
#define reportbuilderJSON_PORT_OBJECT_FORMAT \
"{" \
"\"port\": %u" \
"\"%s\": %u" \
"},"
#define reportbuilderJSON_CONNECTION_OBJECT_FORMAT \
"{" \
"\"local_port\": %u," \
"\"remote_addr\": \"%u.%u.%u.%u:%u\"" \
"\"%s\": %u," \
"\"%s\": \"%u.%u.%u.%u:%u\"" \
"},"
#define reportbuilderJSON_REPORT_FORMAT_PART1 \
"{" \
"\"header\": {" \
"\"report_id\": %u," \
"\"version\": \"%u.%u\"" \
"\"%s\": {" \
"\"%s\": %u," \
"\"%s\": \"%u.%u\"" \
"}," \
"\"metrics\": {" \
"\"listening_tcp_ports\": {" \
"\"ports\": "
"\"%s\": {" \
"\"%s\": {" \
"\"%s\": "
#define reportbuilderJSON_REPORT_FORMAT_PART2 \
"," \
"\"total\": %u" \
"\"%s\": %u" \
"}," \
"\"listening_udp_ports\": {" \
"\"ports\": "
"\"%s\": {" \
"\"%s\": "
#define reportbuilderJSON_REPORT_FORMAT_PART3 \
"," \
"\"total\": %u" \
"\"%s\": %u" \
"}," \
"\"network_stats\": {" \
"\"bytes_in\": %u," \
"\"bytes_out\": %u," \
"\"packets_in\": %u," \
"\"packets_out\": %u" \
"\"%s\": {" \
"\"%s\": %u," \
"\"%s\": %u," \
"\"%s\": %u," \
"\"%s\": %u" \
"}," \
"\"tcp_connections\": {" \
"\"established_connections\": {" \
"\"connections\": "
"\"%s\": {" \
"\"%s\": {" \
"\"%s\": "
#define reportbuilderJSON_REPORT_FORMAT_PART4 \
"," \
"\"total\": %u" \
"\"%s\": %u" \
"}" \
"}" \
"}," \
"\"%s\": {" \
"\"stack_high_water_mark\": [" \
"{" \
"\"%s\": %u" \
"}" \
"]," \
"\"task_numbers\": [" \
"{" \
"\"%s\": "
#define reportbuilderJSON_REPORT_FORMAT_PART5 \
"}" \
"]" \
"}" \
"}"
/*-----------------------------------------------------------*/
/**
@ -158,6 +176,24 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
const Connection_t * pxConnectionsArray,
uint32_t ulConnectionsArrayLength,
uint32_t * pulOutCharsWritten );
/**
* @brief Write task ID array to the given buffer as a JSON array.
*
* @param[in] pcBuffer The buffer to write the array of task IDs.
* @param[in] ulBufferLength The length of the buffer.
* @param[in] pulTaskIdArray The array containing the task IDs.
* @param[in] pulTaskIdArrayLength Length of the pulTaskIdsArray array.
* @param[out] pulOutCharsWritten Number of characters written to the buffer.
*
* @return #ReportBuilderSuccess if the array is successfully written;
* #ReportBuilderBufferTooSmall if the buffer cannot hold the full array.
*/
static eReportBuilderStatus prvWriteTaskIdArray( char * pcBuffer,
uint32_t ulBufferLength,
const uint32_t * pulTaskIdArray,
uint32_t pulTaskIdArrayLength,
uint32_t * pulOutCharsWritten );
/*-----------------------------------------------------------*/
static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
@ -168,7 +204,7 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
{
char * pcCurrentWritePos = pcBuffer;
uint32_t i, ulRemainingBufferLength = ulBufferLength;
int32_t ulCharactersWritten;
int32_t lCharactersWritten;
eReportBuilderStatus eStatus = eReportBuilderSuccess;
configASSERT( pcBuffer != NULL );
@ -190,20 +226,20 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
/* Write the array elements. */
for( i = 0; ( ( i < ulOpenPortsArrayLength ) && ( eStatus == eReportBuilderSuccess ) ); i++ )
{
ulCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_PORT_OBJECT_FORMAT,
pusOpenPortsArray[ i ] );
lCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_PORT_OBJECT_FORMAT,
DEFENDER_REPORT_PORT_KEY,
pusOpenPortsArray[ i ] );
if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
eStatus = eReportBuilderBufferTooSmall;
break;
}
else
{
ulRemainingBufferLength -= ( uint32_t ) ulCharactersWritten;
pcCurrentWritePos += ulCharactersWritten;
ulRemainingBufferLength -= ( uint32_t ) lCharactersWritten;
pcCurrentWritePos += lCharactersWritten;
}
}
@ -222,6 +258,7 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
*pcCurrentWritePos = reportbuilderJSON_ARRAY_CLOSE_MARKER;
ulRemainingBufferLength -= 1;
pcCurrentWritePos += 1;
*pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
}
else
{
@ -229,11 +266,6 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
}
}
if( eStatus == eReportBuilderSuccess )
{
*pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
}
return eStatus;
}
/*-----------------------------------------------------------*/
@ -246,7 +278,7 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
{
char * pcCurrentWritePos = pcBuffer;
uint32_t i, ulRemainingBufferLength = ulBufferLength;
int32_t ulCharactersWritten;
int32_t lCharactersWritten;
eReportBuilderStatus eStatus = eReportBuilderSuccess;
const Connection_t * pxConn;
@ -270,25 +302,26 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
for( i = 0; ( ( i < ulConnectionsArrayLength ) && ( eStatus == eReportBuilderSuccess ) ); i++ )
{
pxConn = &( pxConnectionsArray[ i ] );
ulCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_CONNECTION_OBJECT_FORMAT,
pxConn->usLocalPort,
( pxConn->ulRemoteIp >> 24 ) & 0xFF,
( pxConn->ulRemoteIp >> 16 ) & 0xFF,
( pxConn->ulRemoteIp >> 8 ) & 0xFF,
( pxConn->ulRemoteIp ) & 0xFF,
pxConn->usRemotePort );
if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
lCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_CONNECTION_OBJECT_FORMAT,
DEFENDER_REPORT_LOCAL_PORT_KEY,
pxConn->usLocalPort,
DEFENDER_REPORT_REMOTE_ADDR_KEY,
( pxConn->ulRemoteIp >> 24 ) & 0xFF,
( pxConn->ulRemoteIp >> 16 ) & 0xFF,
( pxConn->ulRemoteIp >> 8 ) & 0xFF,
( pxConn->ulRemoteIp ) & 0xFF,
pxConn->usRemotePort );
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
eStatus = eReportBuilderBufferTooSmall;
break;
}
else
{
ulRemainingBufferLength -= ulCharactersWritten;
pcCurrentWritePos += ulCharactersWritten;
ulRemainingBufferLength -= lCharactersWritten;
pcCurrentWritePos += lCharactersWritten;
}
}
@ -307,6 +340,7 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
*pcCurrentWritePos = reportbuilderJSON_ARRAY_CLOSE_MARKER;
ulRemainingBufferLength -= 1;
pcCurrentWritePos += 1;
*pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
}
else
{
@ -314,9 +348,77 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
}
}
return eStatus;
}
/*-----------------------------------------------------------*/
static eReportBuilderStatus prvWriteTaskIdArray( char * pcBuffer,
uint32_t ulBufferLength,
const uint32_t * pulTaskIdArray,
uint32_t pulTaskIdArrayLength,
uint32_t * pulOutCharsWritten )
{
char * pcCurrentWritePos = pcBuffer;
uint32_t i, ulRemainingBufferLength = ulBufferLength;
int32_t lCharactersWritten;
eReportBuilderStatus eStatus = eReportBuilderSuccess;
configASSERT( pcBuffer != NULL );
configASSERT( pulTaskIdArray != NULL );
configASSERT( pulOutCharsWritten != NULL );
/* Write the JSON array open marker. */
if( ulRemainingBufferLength > 1 )
{
*pcCurrentWritePos = reportbuilderJSON_ARRAY_OPEN_MARKER;
ulRemainingBufferLength -= 1;
pcCurrentWritePos += 1;
}
else
{
eStatus = eReportBuilderBufferTooSmall;
}
/* Write the array elements. */
for( i = 0; ( ( i < pulTaskIdArrayLength ) && ( eStatus == eReportBuilderSuccess ) ); i++ )
{
lCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
"%u,",
pulTaskIdArray[ i ] );
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
eStatus = eReportBuilderBufferTooSmall;
}
else
{
ulRemainingBufferLength -= ( uint32_t ) lCharactersWritten;
pcCurrentWritePos += lCharactersWritten;
}
}
if( eStatus == eReportBuilderSuccess )
{
*pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
/* Discard the last comma. */
if( pulTaskIdArrayLength > 0 )
{
pcCurrentWritePos -= 1;
ulRemainingBufferLength += 1;
}
/* Write the JSON array close marker. */
if( ulRemainingBufferLength > 1 )
{
*pcCurrentWritePos = reportbuilderJSON_ARRAY_CLOSE_MARKER;
ulRemainingBufferLength -= 1;
pcCurrentWritePos += 1;
*pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
}
else
{
eStatus = eReportBuilderBufferTooSmall;
}
}
return eStatus;
@ -332,9 +434,10 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
uint32_t * pulOutReportLength )
{
char * pcCurrentWritePos = pcBuffer;
uint32_t ulRemainingBufferLength = ulBufferLength, bufferWritten;
uint32_t ulRemainingBufferLength = ulBufferLength;
uint32_t bufferWritten;
eReportBuilderStatus eStatus = eReportBuilderSuccess;
int32_t ulCharactersWritten;
int32_t lCharactersWritten;
configASSERT( pcBuffer != NULL );
configASSERT( pxMetrics != NULL );
@ -358,22 +461,29 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
/* Write part1. */
if( eStatus == eReportBuilderSuccess )
{
ulCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART1,
ulReportId,
ulMajorReportVersion,
ulMinorReportVersion );
if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
lCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART1,
DEFENDER_REPORT_HEADER_KEY,
DEFENDER_REPORT_ID_KEY,
ulReportId,
DEFENDER_REPORT_VERSION_KEY,
ulMajorReportVersion,
ulMinorReportVersion,
DEFENDER_REPORT_METRICS_KEY,
DEFENDER_REPORT_TCP_LISTENING_PORTS_KEY,
DEFENDER_REPORT_PORTS_KEY
);
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 1." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
ulRemainingBufferLength -= ulCharactersWritten;
pcCurrentWritePos += ulCharactersWritten;
ulRemainingBufferLength -= lCharactersWritten;
pcCurrentWritePos += lCharactersWritten;
}
}
@ -400,20 +510,24 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
/* Write part2. */
if( eStatus == eReportBuilderSuccess )
{
ulCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART2,
pxMetrics->ulOpenTcpPortsArrayLength );
if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
lCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART2,
DEFENDER_REPORT_TOTAL_KEY,
pxMetrics->ulOpenTcpPortsArrayLength,
DEFENDER_REPORT_UDP_LISTENING_PORTS_KEY,
DEFENDER_REPORT_PORTS_KEY
);
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 2." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
ulRemainingBufferLength -= ulCharactersWritten;
pcCurrentWritePos += ulCharactersWritten;
ulRemainingBufferLength -= lCharactersWritten;
pcCurrentWritePos += lCharactersWritten;
}
}
@ -440,24 +554,34 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
/* Write part3. */
if( eStatus == eReportBuilderSuccess )
{
ulCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART3,
pxMetrics->ulOpenUdpPortsArrayLength,
pxMetrics->pxNetworkStats->ulBytesReceived,
pxMetrics->pxNetworkStats->ulBytesSent,
pxMetrics->pxNetworkStats->ulPacketsReceived,
pxMetrics->pxNetworkStats->ulPacketsSent );
if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
lCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART3,
DEFENDER_REPORT_TOTAL_KEY,
pxMetrics->ulOpenUdpPortsArrayLength,
DEFENDER_REPORT_NETWORK_STATS_KEY,
DEFENDER_REPORT_BYTES_IN_KEY,
pxMetrics->pxNetworkStats->ulBytesReceived,
DEFENDER_REPORT_BYTES_OUT_KEY,
pxMetrics->pxNetworkStats->ulBytesSent,
DEFENDER_REPORT_PKTS_IN_KEY,
pxMetrics->pxNetworkStats->ulPacketsReceived,
DEFENDER_REPORT_PKTS_OUT_KEY,
pxMetrics->pxNetworkStats->ulPacketsSent,
DEFENDER_REPORT_TCP_CONNECTIONS_KEY,
DEFENDER_REPORT_ESTABLISHED_CONNECTIONS_KEY,
DEFENDER_REPORT_CONNECTIONS_KEY
);
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 3." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
ulRemainingBufferLength -= ulCharactersWritten;
pcCurrentWritePos += ulCharactersWritten;
ulRemainingBufferLength -= lCharactersWritten;
pcCurrentWritePos += lCharactersWritten;
}
}
@ -484,26 +608,67 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
/* Write part4. */
if( eStatus == eReportBuilderSuccess )
{
ulCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART4,
pxMetrics->ulEstablishedConnectionsArrayLength );
if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
lCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART4,
DEFENDER_REPORT_TOTAL_KEY,
pxMetrics->ulEstablishedConnectionsArrayLength,
DEFENDER_REPORT_CUSTOM_METRICS_KEY,
DEFENDER_REPORT_NUMBER_KEY,
pxMetrics->ulStackHighWaterMark,
DEFENDER_REPORT_NUMBER_LIST_KEY
);
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 4." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
ulRemainingBufferLength -= ulCharactersWritten;
pcCurrentWritePos += ulCharactersWritten;
ulRemainingBufferLength -= lCharactersWritten;
pcCurrentWritePos += lCharactersWritten;
}
}
/* Write task ids array. */
if( eStatus == eReportBuilderSuccess )
{
eStatus = prvWriteTaskIdArray( pcCurrentWritePos,
ulRemainingBufferLength,
pxMetrics->pulTaskIdArray,
pxMetrics->ulTaskIdArrayLength,
&( bufferWritten ) );
if( eStatus == eReportBuilderSuccess )
{
pcCurrentWritePos += bufferWritten;
ulRemainingBufferLength -= bufferWritten;
}
else
{
LogError( ( "Failed to write task ID array." ) );
}
}
/* Write part5. */
if( eStatus == eReportBuilderSuccess )
{
*pulOutReportLength = ulBufferLength - ulRemainingBufferLength;
lCharactersWritten = snprintf( pcCurrentWritePos,
ulRemainingBufferLength,
reportbuilderJSON_REPORT_FORMAT_PART5 );
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 5." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
ulRemainingBufferLength -= lCharactersWritten;
pcCurrentWritePos += lCharactersWritten;
*pulOutReportLength = ulBufferLength - ulRemainingBufferLength;
}
}
return eStatus;

@ -41,7 +41,13 @@ typedef enum
} eReportBuilderStatus;
/**
* @brief Represents metrics to be included in the report.
* @brief Represents metrics to be included in the report, including custom metrics.
*
* This demo demonstrates the use of the stack high water mark and list of
* running task ids as custom metrics sent to AWS IoT Device Defender service.
*
* For more information on custom metrics, refer to the following AWS document:
* https://docs.aws.amazon.com/iot/latest/developerguide/dd-detect-custom-metrics.html
*/
typedef struct ReportMetrics
{
@ -52,6 +58,10 @@ typedef struct ReportMetrics
uint32_t ulOpenUdpPortsArrayLength;
Connection_t * pxEstablishedConnectionsArray;
uint32_t ulEstablishedConnectionsArrayLength;
/* Custom metrics */
uint32_t ulStackHighWaterMark;
uint32_t * pulTaskIdArray;
uint32_t ulTaskIdArrayLength;
} ReportMetrics_t;
/**

@ -1 +1 @@
Subproject commit e15db4c22cfdd534d1e0693cdbdf467c7b09e897
Subproject commit ce98843504b037a81fbfbccd90d90d6f2bb1f417
Loading…
Cancel
Save